Avoid the use of magic numbers in code when possible. Magic numbers are constant values that represent either an arbitrary value (such as a determined appropriate buffer size) or a malleable concept (such as the age a person is considered an adult, which could change between geopolitical boundaries). Rather, use appropriately named symbolic constants to clarify the intent of the code. In addition, if a specific value needs to be changed, reassigning a symbolic constant once is more efficient and less error prone than replacing every instance of the value.
Non-Compliant Code Example
The meaning of the numeric literal 18 is not clear in this example.
/* ... */ if (age >= 18) { /* Take action */ } else { /* Take a different action */ } /* ... */
Compliant Solution
The compliant solution replaces 18 with the symbolic constant ADULT_AGE
to clarify the meaning of the code.
When declaring immutable symbolic values, such as ADULT_AGE
, it is best to declare them as a constant in accordance with DCL00-A. Declare immutable values using enum or const.
enum { ADULT_AGE=18 }; /* ... */ if (age >= ADULT_AGE) { /* Take action */ } else { /* Take a different action */ } /* ... */
Exceptions
DCL06-EX1: While replacing numeric constants with a symbolic constant is often a good practice, it can be taken too far. Exceptions can be made for constants that are themselves the abstraction you want to represent, as in this compliant solution.
x = (-b + sqrt(b*b - 4*a*c)) / (2*a);
Replacing numeric constants with symbolic constants in this example does nothing to improve the readability of the code, and may in fact make the code more difficult to read:
enum { TWO = 2 }; /* a scalar */ enum { FOUR = 4 }; /* a scalar */ enum { SQUARE = 2 }; /* an exponent */ x = (-b + sqrt(pow(b, SQUARE) - FOUR*a*c))/ (TWO * a);
When implementing recommendations, it is always necessary to use sound judgment.
Risk Assessment
Using numeric literals makes code more difficult to read and understand. Buffer overruns are frequently a consequence of a magic number being changed in one place (like an array declaration) but not elsewhere (like a loop through an array).
Recommendation |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
DCL06-A |
1 (low) |
1 (unlikely) |
2 (medium) |
P2 |
L3 |
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[[Henricson 1992]] Chapter 10, "Constants"
[[ISO/IEC 9899-1999]] Section 6.7, "Declarations"
DCL05-A. Use typedefs to improve code readability 02. Declarations and Initialization (DCL) DCL07-A. Include the appropriate type information in function declarators