DCL42-C. Only call functions with the unsequenced or reproducible attributes if they actually have the asserted property
C has function attributes reproducible and unsequenced that assert certain properties that allow compilers to optimize by changing the number of times and locations where such functions are called. The attribute reproducible means that a function is effectiveless and idempotent. The attribute unsequenced means that a function is stateless, effectless, idempotent and independent. The rigorous definitions of these terms can be found in the C Standard, 6.7.13.8 [ ISO/IEC 9899:2024 ]. The paper that proposed adding these attributes to the standard [ JTC1/SC22/WG14 N2956 ] gave these simplified versions of them:
- stateless: function that does not define mutable static or thread-local objects (nor do functions that are called by it)
- effectless: function that does not have observable side effects
- idempotent: repeated evaluation gives the same result (hence may read global state)
- independent: does not depend on other state than the arguments or constants (hence may write to globals)
It is the programmer's responsibility to ensure that functions with these attributes actually meet all of those criteria. If they do not, calling them results in undefined behavior , according to the C Standard, 6.7.13.8.1, paragraph 3 [ ISO/IEC 9899:2024 ]:
if a definition that does not have the asserted property is accessed by a function declaration or a function pointer with a type that has the attribute, the behavior is undefined.
See also undefined behavior 83 .
Noncompliant Code Example (reproducible)
In this noncompliant code example, the adjust() function does not have the idempotence property that is implied by the reproducible attribute (repeating a call will result in changing the values by 6 and 4 instead of just by 3 and 2), so calling it results in undefined behavior.
void adjust(unsigned *restrict x, unsigned *restrict y) [[reproducible]] {
*x -= 3;
*y += 2;
}
Compliant Solution (remove attribute)
In this compliant solution, the reproducible attribute has been removed.
void adjust(unsigned *restrict x, unsigned *restrict y) {
*x -= 3;
*y += 2;
}
Compliant Solution (change behavior)
In this compliant solution, the adjust() operation performs a different operation that is actually idempotent (setting or clearing the same bits twice in a row won't change the value the second time).
void adjust(unsigned *restrict x, unsigned *restrict y) [[reproducible]] {
*x &= ~3;
*y |= 2;
}
Noncompliant Code Example (unsequenced)
In this noncompliant code example, the add_some() function does not have the independence property that is implied by the unsequenced attribute (the to_add global variable has different values each time it's called), so calling it results in undefined behavior.
int to_add = 2;
int add_some(int x) [[unsequenced]] {
return x + to_add;
}
int main(void) {
add_some(-1);
to_add = 1;
return add_some(-1);
}
Compliant Solution (replace attribute)
In this compliant solution, the unsequenced attribute has been removed and replaced with the weaker reproducible attribute, which does not assert independence.
int to_add = 2;
int add_some(int x) [[reproducible]] {
return x + to_add;
}
int main(void) {
add_some(-1);
to_add = 1;
return add_some(-1);
}
Compliant Solution (change behavior)
In this compliant solution, the to_add variable is constant, so the add_some() function actually is independent.
const int to_add = 1;
int add_some(int x) [[unsequenced]] {
return x + to_add;
}
int main(void) {
add_some(-1);
return add_some(-1);
}
Risk Assessment
Calling functions with the unsequenced or reproducible attributes that do not actually have the asserted property is undefined behavior 83 .
| Rule | Severity | Likelihood | Detectable | Repairable | Priority | Level |
|---|---|---|---|---|---|---|
| DCL42-C | Low | Unlikely | No | Yes | P2 | L3 |
Automated Detection
Tool | Version | Checker | Description |
|---|
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website .
Bibliography
| [ ISO/IEC 9899:2024 ] | 6.7.13.8, "Standard attributes for function types" |
| [ JTC1/SC22/WG14 N2956 ] | Unsequenced Functions |