CWE-768 is a logic weakness that lives in a single line. The product has a conditional with several logical expressions, and one of the non-leading expressions can produce side effects. Short circuit evaluation may prevent those side effects from happening, which leaves an unexpected state after the conditional runs.
MITRE lists C explicitly and marks the entry as not language specific. Most mainstream languages short circuit AND and OR, so the pattern is widely portable.
How it happens
In an AND, if the left side is false, the right side is never evaluated. In an OR, if the left side is true, the right side is skipped. This is well defined in the C standard. It becomes a bug when the right side does something besides answer a question: increments a counter, advances a buffer, acquires or releases a resource, or validates and normalizes input.
// Vulnerable: advance() only runs when authorized is true
if (authorized && advance(&cursor)) {
handle(cursor);
}
// later code assumes cursor always moved
MITRE points out why this survives testing. If the first condition of an OR is assumed to be true under normal circumstances, or the first condition of an AND is assumed false, then any later condition may contain its own logic errors that review and tests do not detect. The code path with the skipped side effect barely runs in normal operation.
MITRE also notes that heavy use of short circuit evaluation can decrease maintainability. The next person to touch the line may not see that the second operand is doing real work.
What an attacker gains
The record states that consequences vary widely by context. If an attacker finds the unexpected state, they may cause information exposure, a crash, or in the worst case gain complete control of the system. MITRE's wording is that exploitation may be possible to gain arbitrary control, but that depends on what the skipped side effect was supposed to guard. A skipped bounds update differs greatly from a skipped logging call.
The record lists no observed CVEs for this entry, so rely on the description and reason from your own code.
How to find it
MITRE says static analysis can find some instances by analyzing code without running it. Beyond tools, a focused review helps:
- Search for conditions that mix a comparison with a function call on the right side of an AND or OR.
- For each call, ask whether it changes state. If yes, ask whether later code assumes the change happened.
- Write a test for the branch where the left side decides the result, since that is the branch that skips the work.
Branch coverage reports are useful here. A right operand that never executes in your tests is a candidate.
How to fix it
MITRE's guidance: minimizing the number of statements in a conditional that produce side effects reduces the chance that short circuiting changes control flow in unexpected ways. In practice:
- Separate the work from the test. Do the side effect in its own statement, then branch on the stored result.
- Keep conditions pure. A condition should answer a question and change nothing.
- Put the cheap, guarding check first deliberately, and document when ordering matters.
- Add tests for the skipped branch.
// Fix: the side effect always happens, the decision is separate
bool moved = advance(&cursor);
if (authorized && moved) {
handle(cursor);
}
The meaning is clearer, and a reader no longer needs to remember how && evaluates.
Quick check
Is short circuit evaluation itself a defect?
No. It is well defined and useful. The weakness appears when a skipped operand was supposed to change program state.
Why do tests rarely catch this?
Normal runs follow the common outcome of the first operand, so the branch that skips the second operand is seldom exercised.
What is the simplest refactor?
Move the call with the side effect into its own statement before the conditional, and test the stored result.