Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
bgColor#FFcccc
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

...

Code Block
bgColor#ccccff
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;
}

Non-Compliant Code Example

...

Code Block
bgColor#FFcccc
void* AllocBlocks(size_t cBlocks) {
  if (cBlocks == 0) return NULL; 
  unsigned long long alloc = cBlocks * 16;
  return (alloc < UINT_MAX) ? malloc(cBlocks * 16) : NULL;
}

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.

...

Code Block
bgColor#ccccff
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;
}

...