Increment or decrement inside a sizeof operand never executes
ID |
objectivec.correctness.side_effect_in_sizeof |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Dead Code |
Language |
Objective-C |
Description
Reports an increment or decrement appearing inside the parentheses of a sizeof operand - sizeof(i)`, `sizeof(i), sizeof(values[i])`, `sizeof(*p). An increment elsewhere in the same expression, such as sizeof(values) + i`, is not reported, and neither are occurrences inside a comment or a string literal. An operand that wraps the increment in a further pair of parentheses - `sizeof(*(p)) - is beyond what a lexical scan can bound and is not reported.
Rationale
sizeof is resolved from the operand’s type, and outside the variable-length-array case the operand is never evaluated. The increment therefore does not happen: the counter the surrounding code relies on is never advanced, so a loop that walks a buffer with sizeof(*cursor++) stays on the first element forever. Nothing in the source marks the difference between the increment that runs and the one that does not, and the compiler usually issues no diagnostic, so the loop simply behaves as if the statement were missing.
The following code illustrates the pattern detected by this rule:
@implementation Buffers
- (void)withSideEffects {
NSInteger index = 0;
NSInteger values[8] = {0};
NSInteger *cursor = values;
// FLAGGED: Increment or decrement inside a sizeof operand never executes
size_t postIncrement = sizeof(index++);
// FLAGGED: Increment or decrement inside a sizeof operand never executes
size_t preIncrement = sizeof(++index);
// FLAGGED: Increment or decrement inside a sizeof operand never executes
size_t postDecrement = sizeof(index--);
// FLAGGED: Increment or decrement inside a sizeof operand never executes
size_t subscripted = sizeof(values[index++]);
// FLAGGED: Increment or decrement inside a sizeof operand never executes
size_t dereferenced = sizeof(*cursor++);
NSLog(@"%zu %zu %zu %zu %zu %ld", postIncrement, preIncrement, postDecrement,
subscripted, dereferenced, (long)index);
}
@end
Remediation
Move the increment out of the sizeof expression and give it its own statement, before or after the one that uses the size. Where the size of the pointed-to element is what is wanted, sizeof(*cursor) states it without touching the cursor, and the advance can then be written where it is meant to happen.