Octal integer literal
ID |
objectivec.maintainability.octal_constant |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
medium |
Remediation Effort |
low |
Resource |
Numeric Literal |
Language |
Objective-C |
Description
Reports an integer literal written with a leading 0 and at least one further digit, which the compiler reads as base 8. A lone 0, a fraction such as 0.5 or 1.0755, a hexadecimal literal and a decimal literal are not reported, and neither are occurrences inside a comment or a string literal. An integer suffix - 0777L, 0644U - is part of the literal and is reported.
Rationale
The leading zero is the whole notation, so it is easy to write by accident and easy to read past. 010 is eight, not ten, and a column of values lined up as 0755, 0644, 0600 for readability turns every one of them into a different number than it appears to be. Where the leading zero was added purely to align digits - a date part, a version component, a zero-padded identifier - the value silently changes, and 08 and 09 do not even compile.
The following code illustrates the pattern detected by this rule:
@implementation Modes
- (void)permissions {
// FLAGGED: Octal integer literal
NSInteger mode = 0755;
// FLAGGED: Octal integer literal
NSInteger mask = 0644;
// FLAGGED: Octal integer literal
long wide = 0777L;
// FLAGGED: Octal integer literal
NSInteger padded = 007;
NSLog(@"%ld %ld %ld %ld", (long)mode, (long)mask, wide, (long)padded);
}
@end
Remediation
Drop the leading zero if a decimal value was meant: 010 becomes 10. Where octal really is intended - POSIX file modes are the usual case - keep it, but give the value a name that says so, as in static const mode_t kPrivateDirMode = 0700;, so the notation is deliberate rather than incidental.