Octal Values
ID |
php.octal_values |
Severity |
critical |
Remediation Complexity |
trivial |
Remediation Risk |
medium |
Remediation Effort |
low |
Resource |
Code Smell |
Language |
Php |
Tags |
code-style, reliability |
Description
Reports an octal integer literal that is not being used as a Unix file mode.
PHP writes octal with a bare leading zero, 0644. The literal reads like a decimal number and is
not one, and outside a permission bitmask neither base 8 nor the leading zero carries meaning a
reader can act on.
File modes are exempt: octal is the conventional notation for permissions and umasks, and 0755 is
how the PHP manual documents them. See Configuration for how a file mode is recognised.
Rationale
$slots = 010; // this is 8, not 10
const RETRY_BUDGET = 0123; // octal bound to an ordinary constant
$head = 010; // an offset written in base 8 for no reason
The leading-zero form is a silent trap. 010 is decimal 8, and nothing on the line says so: the
literal looks like the decimal number ten to every reader who has not memorised the rule. A count,
a size, a port, a timeout or an array index typed with an accidental leading zero parses and runs
with a different value than the author wrote, and no test that only exercises the happy path will
notice.
The trap has teeth in PHP specifically because a leading zero is how the language writes an aligned
column of numbers. ['0644', '0755'] is a pair of strings and means what it says; dropping the
quotes silently changes both values.
Remediation
Write the value in the base that matches how it is used, and let the name say when a value is a permission.
$slots = 8; // a count, in decimal
const RETRY_BUDGET = 83; // if 83 really was the intent
// If the value is a file mode, say so — then octal is the right notation and is accepted.
$dirPerm = 0755;
chmod($path, 0644);
mkdir($dir, 0750, true);
$options = ['mode' => 0777];
For bit flags, prefer the base that shows the bits: 0b1010 for a bitmask, 0x1F for a byte
pattern. Both are excluded from this rule.
The PHP 8.1 explicit form 0o755 is not reported, because the analyzer’s PHP grammar does not
accept it; only the legacy leading-zero form reaches this rule, which is the form the check is
about — an explicit prefix cannot be misread.
Configuration
A literal is treated as a file mode, and not reported, when either of these says so.
| Property | Meaning | Default |
|---|---|---|
|
Function names whose arguments are permissions or umasks. A call is matched on the last segment of
its callee name, so one entry covers |
|
|
Name words that make a literal a file mode. The name the literal is bound to — a variable, a class
field, a |
|
Add a project’s own permission wrapper to fileModeFunctions to silence findings inside it.