...
Non-Compliant Coding Example
In this This code example is non-compliant code exapmleon systems where size_t is an unsigned 32-bit value and long long is a 64-bit value. In this example, the programmer attempts to prevent against integer by ensuring that tests for integer overflow by assigning the value UINT_MAX to max and testing if length + BLOCK_HEADER_SIZE > max. Because length is declared as size_t, however, the addition is performed as a 32-bit operation and can result in an integer overflow. The comparison with max in this example will always test false. If an overflow occurs, malloc() will allocate insufficient space for mBlock which could lead to a subsequent buffer overflow.
| Code Block | ||
|---|---|---|
| ||
unsigned long long max = UINT_MAX; void *AllocateBlock(size_t length) { struct memBlock *mBlock; if (length + BLOCK_HEADER_SIZE > max) { return NULL; } mBlock = malloc(length + BLOCK_HEADER_SIZE); if (!mBlock) return NULL; /* fill in block header and return data portion */ return mBlock; } |
Compliant Solution
In this compliant solution, the length operand is upcast to (unsigned long long) ensuring that the addition takes place in this size.
| Code Block | ||
|---|---|---|
| ||
void *AllocateBlock(size_t length) { struct memBlock *mBlock; if ((unsigned long long)length + BLOCK_HEADER_SIZE > max) { return NULL; } mBlock = malloc(length + BLOCK_HEADER_SIZE); if (!mBlock) { return NULL; } /* fill in block header and return data portion */ return mBlock; } |
...
There are a couple of problems with this code. The first problem is that this code assumes an implementation where unsigned long long has a least twice the number of bits as size_t. The second problem, assuming an implementation where size_t is a 32-bit value and unsigned long long is represented by a 64-bit value, is that the to be compliant with C99, multiplying two 32-bit numbers in this context must yield a 32-bit result. Any integer overflow resulting from this multiplication will remain undetected by this code, and the expression alloc < UINT_MAX will always be true.
Compliant Solution
In this compliant solution, the cBlocks operand is upcast to (unsigned long long) ensuring that the multiplication takes place in this size.
...