Don't bother reading this, yet. I'm still working on it... Dan
A variadic function – a function declared with a parameter list ending with ellipsis (...) – can accept a varying number of arguments of varying types. Variadic functions are flexible, but they are also hazardous. The compiler can't verify that a given call to a variadic function passes an appropriate number of arguments or that those arguments have appropriate types. Consequently, a runtime call to a variadic function that passes inappropriate arguments yields undefined behavior. Such undefined behavior could be exploited to run arbitrary code.
Non-compliant Code Example
Compliant Solution
An appropriate coding or design technique should be used to avoid the runtime static initialization of namespace scope objects. The best solution is often simply to avoid using such variables, to the extent practical.
Exceptions
When a function call appears in some contexts, notably as the argument in a sizeof expression, the compiler performs overload resolution to determine the result type of the call, but the object code doesn't execute the call at runtime. In that case, calling a variadic function does no harm, and can actually be very useful, especially when using template metaprogramming techniques that exploit SFINAE ("substitution failure is not an error").
typedef char True; typedef struct { char a[2]; } False; template <typename T> True isPtr(T *); False isPtr(...); #define is_ptr(e) (sizeof(isPtr(e)) == sizeof(True))
Risk Assessment
Incorrectly using a variadic function can result in abnormal program termination or unintended information disclosure.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
DCL33-C |
3 (medium) |
2 (probable) |
3 (low) |
P18 |
L1 |
References
[[Dewhurst 03]] Gotcha 55: Runtime Static Initialization