Unreasoned assignment
| Vulnerability potential | Low |
| DDoS potential | None |
This assignment result might be unused or assignment might not take effect
Impact
This covers assignments that accomplish nothing: a self-assignment
x = x, a write to a copy that the caller never sees, an update to a field
that is immediately recomputed, or a store the compiler can prove has no
observable effect. The assignment looks like it changes state but does not.
Functionally the program runs as if the line were absent, which is benign in
isolation but almost always means the author expected an effect that is not
happening — the wrong variable was assigned, a pointer/reference was needed
instead of a value, or a missing volatile made the write disappear. The
consequence is a silent divergence between what the code says it does and what it
actually does.
Vulnerability potential
Mostly a correctness and clarity issue, but the “intended effect did not happen” reading carries some risk.
- If the assignment was meant to update a security-relevant value — clearing a flag, lowering a privilege level, invalidating a cached credential — and it silently has no effect, the system stays in the more-privileged or stale state.
- A missing
volatileon a memory-mapped register or a flag shared with a signal handler/another thread lets the compiler optimize the write away, so a needed hardware or synchronization side effect never occurs, which can defeat a safety or security action.
When the assignment is genuinely redundant (e.g. defensive self-assignment), it has no security relevance.
Technical details
An assignment has no effect when its target’s new value equals its old value, or when the target is not observable after the store. The compiler establishes this with value and liveness analysis and removes the write under the as-if rule.
Common shapes
- Self-assignment.
x = x;orobj.field = obj.field;— frequently a typo for assigning a different member (a.x = b.x). - Write to a by-value copy. Modifying a struct received by value, or a loop-induction copy, when the caller’s object was meant to change; the mutation dies with the copy.
- Optimized-away write. A store to a variable later overwritten on every
path, or to plain (non-
volatile) memory that models hardware/shared state, which the optimizer legally drops because it sees no reader. - Computed-then-discarded.
a + b;style statements, or an assignment to a temporary that is never used.
The volatile qualifier exists to forbid this elimination where the write is
the point (MMIO, sig_atomic_t flags); leaving it off is a frequent root
cause.
Catching the issue
Compilers warn on the obvious cases: Clang’s -Wself-assign and
-Wself-assign-field, and -Wunused-value for expression statements with no
effect. Static analyzers go further — cppcheck selfAssignment /
redundantAssignment, PVS-Studio V570/V587, Coverity, and the Clang Static
Analyzer flag assignments whose value is unobservable. For the pass-by-value
trap, prefer references/pointers and let -Wunused-but-set-parameter help. For
the volatile trap, review every write to hardware registers and to flags
shared with signal handlers or other threads, and confirm the qualifier (or a
proper atomic) is present. In review, treat a no-effect assignment as a question:
what state was supposed to change here?
How to reproduce
Observe that normalize mutates a by-value copy, so the caller’s struct is
unchanged — the assignment has no effect outside the function. Build with
-Wall.
#include <stdio.h>
struct point { int x, y; };
/* takes the struct BY VALUE: assignments touch a local copy only */
void normalize(struct point p) {
p.x = 0; /* no effect on the caller's object */
p.y = 0;
}
int main(void) {
struct point a = {3, 4};
normalize(a); /* intended to reset a, but does nothing */
printf("%d %d\n", a.x, a.y); /* prints "3 4", not "0 0" */
return 0;
}