...
| Code Block | ||
|---|---|---|
| ||
enum { BLOCK_HEADER_SIZE = 16 };
void *AllocateBlock(size_t length) {
struct memBlock *mBlock;
if (length + BLOCK_HEADER_SIZE > (unsigned long long) SIZE_MAX)
return NULL;
mBlock
= (struct memBlock *)malloc(
length + BLOCK_HEADER_SIZE
);
if (!mBlock) return NULL;
/* fill in block header and return data portion */
return mBlock;
}
GCC 3.4.4 produces a warning for this noncompliant code example. |
...
Compliant Solution 1
In this compliant solution, the length operand is upcast to unsigned long long, ensuring that the addition takes place in this size.
| Code Block | ||
|---|---|---|
| ||
h2. Compliant Solution (upcast) In this compliant solution, the {{length}} operand is upcast to {{unsigned long long}}, ensuring that the addition takes place in this size. {code:bgColor=#ccccff} enum { BLOCK_HEADER_SIZE = 16 }; void *AllocateBlock(size_t length) { struct memBlock *mBlock; if ((unsigned long long)length + BLOCK_HEADER_SIZE > SIZE_MAX) { return NULL; mBlock} mBlock = (struct memBlock *)malloc( length + BLOCK_HEADER_SIZE ); if (!mBlock) return NULL; /* fill in block header and return data portion */ return mBlock; } |
This test for integer overflow wrapping is effective only effective when the sizeof(unsigned long long) > sizeof(size_t). If both size_t and unsigned long long types are represented as a 64-bit unsigned value, the result of the addition operation may not be representable as an unsigned long long value.
Compliant Solution
...
(Rearrange Expression)
IIn In this compliant solution, the length operand is subtracted from SIZE_MAX, this ensures that no overflow can occur (ensuring that wrapping cannot occur see INT30-C. Ensure that unsigned integer operations do not wrap).
| Code Block | ||
|---|---|---|
| ||
enum { BLOCK_HEADER_SIZE = 16 };
void *AllocateBlock(size_t length) {
struct memBlock *mBlock;
if (SIZE_MAX - length < BLOCK_HEADER_SIZE) return NULL;
mBlock
= (struct memBlock *)malloc(
length + BLOCK_HEADER_SIZE
);
if (!mBlock) return NULL;
/* fill in block header and return data portion */
return mBlock;
}
|
...
In this noncompliant code example, the programmer attempts to prevent integer overflow wrapping by allocating an unsigned long long integer called alloc and assigning it the result from cBlocks * 16.
...
There are two separate problems with this noncompliant code example. The first problem is that this code assumes an implementation where unsigned long long has a least four more bits than 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 to be compliant with C99, multiplying two 32-bit numbers in this context must yield a 32-bit result. Any integer overflow wrapping resulting from this multiplication will remain undetected by this code, and the expression alloc < UINT_MAX will always be true.
...
In this compliant solution, the cBlocks operand is upcast to unsigned long long, ensuring that the multiplication takes place in this size.
| Code Block | ||
|---|---|---|
| ||
static_assert(
CHAR_BIT * sizeof(unsigned long long) >=
CHAR_BIT * sizeof(size_t) + 4,
"Unable to detect wrapping after multiplication"
);
void* AllocBlocks(size_t cBlocks) {
if (cBlocks == 0) return NULL;
unsigned long long alloc = (unsigned long long)cBlocks * 16;
return (alloc < UINT_MAX) ? malloc(cBlocks * 16) : NULL;
}
|
Note that this code does not prevent overflows wrapping unless the unsigned long long type is at least four bits larger than size_t.
...
| Wiki Markup |
|---|
\[[Dowd 06|AA. C References#Dowd 06]\] Chapter 6, "C Language Issues"
\[[ISO/IEC 9899:1999|AA. C References#ISO/IEC 9899-1999]\] Section 6.3.1, "Arithmetic operands"
\[[ISO/IEC PDTR 24772|AA. C References#ISO/IEC PDTR 24772]\] "FLC Numeric Conversion Errors"
\[[MITRE 07|AA. C References#MITRE 07]\] [CWE ID 681|http://cwe.mitre.org/data/definitions/681.html], "Incorrect Conversion between Numeric Types," and [CWE ID 190|http://cwe.mitre.org/data/definitions/190.html], "Integer Overflow (Wrap or Wraparound)"
\[[Seacord 05a|AA. C References#Seacord 05a]\] Chapter 5, "Integer Security" |
...