
Integer constants are often used as masks or specific bit values. Frequently, these constants are expressed in hexadecimal form to indicate to the programmer how the data might be represented in the machine. However, Hexadecimal integer constants are frequently used in a non-portable manner.
Noncompliant Code Example
The noncompliant code example attempts to take two's complement of a value of type unsigned long
using a mask.
const unsigned long mask = 0xFFFFFFFF; unsigned long x; /* Initialize x */ x = (x ^ mask) + 1;
This code produces the two's complement of x
for implementations where unsigned long
have a precision of 32 bits. However, on implementations where unsigned long
has a precision of 64 bits, this code does not produce the two's complement of x
. Because only the lower order 32-bits are set, the resulting value of mask
is 0x00000000FFFFFFFF.
Compliant Solution
A portable (and safer) way to set all the bits on in an integer constant of type unsigned long
is to define a constant with a value of ~0
.
const unsigned long mask = ~0; unsigned long x; /* Initialize x */ x = (x ^ mask) + 1;
This compliant solution sets all the bits in the value regardless of representation.
Noncompliant Code Example
In this noncompliant code example, a programmer is attempting to set the most significant bit.
const unsigned long mask = 0x80000000; unsigned long x; /* Initialize x */ x = (x ^ mask) + 1;
This code has the desired effect for implementations where unsigned long
have a precision of 32 bits but not on implementations where unsigned long
has a precision of 64 bits.
Compliant Solution
A portable (and safer) way of setting the high order bit is to use a shift expression as in this compliant solution.
const unsigned long mask = (1 << ((sizeof(unsigned long) * CHAR_BIT) - 1)) unsigned long x; /* Initialize x */ x = (x ^ mask) + 1;
Risk Assessment
Vulnerabilities are frequently introduced while porting code. A buffer overflow vulnerability may result, for example, if an incorrectly defined integer constant is used to determine the size of a buffer. It is always best to write portable code, especially when there is no performance overhead for doing so.
Recommendation |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
INT17-C |
high |
probable |
low |
P6 |
L2 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Other Languages
This rule appears in the C++ Secure Coding Standard as INT17-CPP. Define integer constants in an implementation-independent manner.
References
[Dewhurst 02] Gotcha #25, "#define Literals"
[ISO/IEC 9899-1999] Section 6.4.4.1, "Integer constants"