[metadata]
id = "MSC39-C"
type = "rule"
category = "MSC"
number = 39
title = "Do not call va_arg() on a va_list that has an indeterminate value"
description = """
Variadic functions access their variable arguments by usingva_start()to
initialize an object of typeva_list, iteratively invoking theva_arg()macro, and
finally callingva_end(). Theva_listmay be passed as an argument to another
function, but callingva_arg()within that function causes theva_listto have
anindeterminate valuein the calling function. As a result, attempting to read
variable arguments without reinitializing theva_listcan haveunexpected behavior.
According to the C Standard, 7.16, paragraph 3 [ISO/IEC 9899:2024], This
noncompliant code example attempts to check that none of its variable arguments
are zero by passing ava_listto helper functioncontains_zero(). After the call
tocontains_zero(), the value ofapisindeterminate. #include <stdarg.h> #include
<stdio.h> int contains_zero(size_t count, va_list ap) { for (size_t i = 1; i <
count; ++i) { if (va_arg(ap, double) == 0.0) { return 1; } } return 0; } int
print_reciprocals(size_t count, ...) { va_list ap; va_start(ap, count); if
(contains_zero(count, ap)) { va_end(ap); return 1; } for (size_t i = 0; i <
count; ++i) { printf("%f ", 1.0 / va_arg(ap, double)); } va_end(ap); return 0; }
"""
severity = "Low"
likelihood = "Unlikely"
priority = "P2"
level = "L3"
cert_version = "2016 Edition (Wiki)"
last_modified = "Aug 31, 2025"
[rules.cert_c.MSC39-C]
enabled = true
[references]
wiki = "https://wiki.sei.cmu.edu/confluence/display/c/MSC39-C.+Do+not+call+va_arg%28%29+on+a+va_list+that+has+an+indeterminate+value"