Condition is always true
| Vulnerability potential | Low |
| DDoS potential | None |
The corresponding condition is always true
Impact
A condition that the compiler or analyzer can prove is always true means the
branch was not really a decision. Two things follow. First, the else path (or
the code after an early return/break guarded by the condition) is
dead: it can never execute, so any logic placed there — error handling, a
fallback, a security check — is silently inert. Second, the always-true result is
usually a symptom: the programmer intended a real test but wrote one that the
operands can never falsify (a wrong comparison, a tautology, a sign or type
mistake, a confusion between a value and its address). The visible behaviour is
“it always takes this branch”, which may look fine until the day the input that
was supposed to take the other branch arrives.
Vulnerability potential
Usually this is a logic bug with limited direct security impact, but there are real exceptions.
- If the always-true condition is a security check —
if (authorized)whereauthorizedcan never be false because of a coding mistake — the check passes unconditionally and access control is effectively removed. - If the dead
elsebranch contained validation, bounds checking, or error handling, that protection is gone and malformed input flows into code that assumed it had been rejected.
When the condition is merely redundant (genuinely always true and the other branch was never meant to run), there is no security relevance.
Technical details
An analyzer proves a condition constant by tracking value ranges and relationships along each path. Frequent root causes in C/C++:
- Type/range tautology. Comparing an
unsignedvalue with>= 0, or a small enum against a value outside its range, yields a constant the type guarantees. - Wrong operator.
a || bwherea && bwas meant, or!=instead of==, can collapse to a tautology. - Sign/promotion surprises. Integer promotion and the usual arithmetic conversions can make a comparison that looks meaningful constant under the actual operand types.
- Macro expansion. A macro that expands to a constant, or a configuration flag fixed at compile time, makes the condition trivially true in this build.
The compiler legitimately exploits this: it folds the constant, deletes the dead
branch, and may emit -Wtautological-compare. The information is there; the
defect is that the human did not intend it.
Catching the issue
Enable and act on the compiler warnings: GCC/Clang -Wtautological-compare,
-Wtype-limits (part of -Wextra), and -Wtautological-constant-out-of-range-compare
catch the common range tautologies. Static analyzers (Clang Static Analyzer,
Coverity, PVS-Studio’s V547 “expression is always true”, cppcheck) report
provably-constant conditions and the dead code they create; coverage tools that
flag unreachable branches give a second, dynamic signal. In review, be
suspicious of any comparison of an unsigned quantity against zero and of branches
whose else is never observed to run in tests.
How to reproduce
Observe that len >= 0 is always true for an unsigned value, so the
error branch is dead and an oversized length is accepted; compile with
-Wtype-limits.
#include <stddef.h>
#include <string.h>
void copy(char *dst, const char *src, size_t len) {
if (len >= 0) { /* size_t is unsigned: always true */
memcpy(dst, src, len); /* the "reject huge len" else-branch is dead */
} else {
/* unreachable: intended to reject invalid lengths */
return;
}
}