...
This compliant solution uses a compare-and-exchange to guarantee that the correct value is stored in flag. All updates are visible to other threads. The call to atomic_compare_exchange_weak() is in a loop in conformance with .
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <stdatomic.h>
#include <stdbool.h>
static atomic_bool flag = ATOMIC_VAR_INIT(false);
void init_flag(void) {
atomic_init(&flag, false);
}
void toggle_flag(void) {
bool old_flag = atomic_load(&flag);
bool new_flag;
do {
new_flag = !old_flag;
} while (!atomic_compare_exchange_weak(&flag, &old_flag, new_flag));
}
bool get_flag(void) {
return atomic_load(&flag);
} |
An alternative solution is to use the atomic_flag data type for managing Boolean values atomically. However, atomic_flag does not support a toggle operation.
Compliant Solution (Compound Assignment)
This compliant solution uses the ^= assignment operation to toggle flag. This operation is guaranteed to be atomic, according to the C Standard, 6.5.17.5, paragraph 3 [ISO/IEC 9899:2024]. This operation performs a bitwise-exclusive-or between its arguments, but for Boolean arguments, this is equivalent to negation.
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <stdatomic.h>
#include <stdbool.h>
static atomic_bool flag = ATOMIC_VAR_INIT(false);
void toggle_flag(void) {
flag ^= 1;
}
bool get_flag(void) {
return flag;
} |
An alternative solution is to use a mutex to protect the atomic operation, but this solution loses the performance benefits of atomic variables.
Noncompliant Code Example
This noncompliant code example takes an atomic global variable n and computes n + (n - 1) + (n - 2) + ... + 1, using the formula n * (n + 1) / 2:
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <stdatomic.h>
atomic_int n = ATOMIC_VAR_INIT(0);
int compute_sum(void) {
return n * (n + 1) / 2;
} |
The value of n may change between the two atomic reads of n in the expression, yielding an incorrect result.
Compliant Solution
This compliant solution passes the atomic variable as a function argument, forcing the variable to be copied and guaranteeing a correct result. Note that the function's formal parameter need not be atomic, and the atomic variable can still be passed as an actual argument.
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <stdatomic.h>
int compute_sum(int n) {
return n * (n + 1) / 2;
}
|
Risk Assessment
When operations on atomic variables are assumed to be atomic, but are not atomic, surprising data races can occur, leading to corrupted data and invalid control flow.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
|---|---|---|---|---|---|
CON40-C | Medium | Probable | Medium | P8 | L2 |
Automated Detection
Tool | Version | Checker | Description | |||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Astrée |
| multiple-atomic-accesses | Partially checked | |||||||
| Axivion Bauhaus Suite |
| CertC-CON40 | ||||||||
| CodeSonar |
| CONCURRENCY.MAA | Multiple Accesses of Atomic | |||||||
| Coverity |
| EVALUATION_ORDER (partial) MISRA 2012 Rule 13.2 VOLATILE_ATOICITY (possible) | Implemented | |||||||
| Cppcheck Premium |
| premium-cert-con40-c | Partially implemented | |||||||
| Helix QAC |
| C1114, C1115, C1116 C++3171, C++4150 | ||||||||
| Klocwork |
| CERT.CONC.ATOMIC_TWICE_EXPR | ||||||||
| Parasoft C/C++test |
| CERT_C-CON40-a | Do not refer to an atomic variable twice in an expression | |||||||
| Polyspace Bug Finder |
| CERT C: Rule CON40-C | Checks for:
Rule fully covered. | |||||||
| RuleChecker |
| multiple-atomic-accesses | Partially checked |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
Key here (explains table format and definitions)
Taxonomy | Taxonomy item | Relationship |
|---|---|---|
| CWE 2.11 | CWE-366, Race Condition within a Thread | 2017-07-07: CERT: Rule subset of CWE |
CERT-CWE Mapping Notes
Key here for mapping notes
CWE-366 and CON40-C
CON40-C = Subset( CON43-C) Intersection( CON32-C, CON40-C) = Ø
CWE-366 = Union( CON40-C, list) where list =
- C data races that do not involve an atomic variable used twice within an expression
Bibliography
6.5.17.3, "Compound Assignment" |