Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: REM Cost Reform

...

Code Block
bgColor#FFcccc
langc
#include <stdlib.h>
#include <stdint.h>  /* For SIZE_MAX */
 
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;
}

Some compilers will diagnose this condition.

...

Code Block
bgColor#ccccff
langc
#include <stdlib.h>
#include <stdint.h>


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 = (struct memBlock *)malloc(
    length + BLOCK_HEADER_SIZE
  );
  if (!mBlock) { return NULL; }
  /* Fill in block header and return data portion */

  return mBlock;
}

This test for wrapping is effective only when the sizeof(unsigned long long) > sizeof(size_t). If both size_t and unsigned long long types are represented as 64-bit unsigned values, the result of the addition operation may not be representable as an unsigned long long value.

...

Code Block
bgColor#ccccff
langc
#include <stdlib.h>
#include <stdint.h>
 
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;
}

Noncompliant Code Example

...

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

Two problems occur in this noncompliant code example. The first problem is that this code assumes an BB. Definitions#implementation implementation where unsigned long long has at least 4 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 C, multiplying two 32-bit numbers in this context must yield a 32-bit result. Any wrapping resulting from this multiplication will remain undetected by this code, and the expression alloc < UINT_MAX will always be true.

...

Code Block
bgColor#ccccff
langc
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
 
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 wrapping unless the unsigned long long type is at least 4 bits larger than size_t.

...

Code Block
bgColor#FFcccc
langc
#include <stdlib.h>
 
void func(wchar_t *pwcs, const char *restrict s, size_t n) {
  size_t count_modified = mbstowcs(pwcs, s, n);
  if (count_modified == -1) {
    /* Handle error */
  }
}

Compliant Solution (size_t)

...

Code Block
bgColor#ccccff
langc
#include <stdlib.h>
 
void func(wchar_t *pwcs, const char *restrict s, size_t n) {
  size_t count_modified = mbstowcs(pwcs, s, n);
  if (count_modified == (size_t)-1) {
    /* Handle error */
  }
}

Risk Assessment

Failure to cast integers before comparing or assigning them to a larger integer size can result in software BB. Definitions#vulnerability vulnerabilities that can allow the execution of arbitrary code by an attacker with the permissions of the vulnerable process.

Rule

Severity

Likelihood

Remediation Cost

Detectable

Repairable

Priority

Level

INT18-C

high

High

Likely

likely

No

medium

Yes

P18

L1

Automated Detection

Tool

Version

Checker

Description

Astrée
Include Page
Astrée_V
Astrée_V

Supported, but no explicit checker
CodeSonar
Include Page
CodeSonar_V
CodeSonar_V

LANG.TYPE.AWID
LANG.TYPE.OWID
LANG.CAST.VALUE
LANG.CAST.COERCE
ALLOC.SIZE.ADDOFLOW
ALLOC.SIZE.IOFLOW
ALLOC.SIZE.MULOFLOW
ALLOC.SIZE.SUBUFLOW
ALLOC.SIZE.TRUNC
MISC.MEM.SIZE.ADDOFLOW
MISC.MEM.SIZE.BAD
MISC.MEM.SIZE.MULOFLOW
MISC.MEM.SIZE.SUBUFLOW
MISC.MEM.SIZE.TRUNC

Expression value widened by assignment
Expression value widened by other operand
Cast alters value
Coercion alters value
Addition

Overflow

overflow of

Allocation Size

allocation size
Integer

Overflow

overflow of

Allocation Size

allocation size
Multiplication

Overflow

overflow of

Allocation Size

allocation size
Subtraction

Underflow

underflow of

Allocation Size

allocation size
Truncation of

Allocation Size

allocation size
Addition

Overflow

overflow of

Size

size
Unreasonable

Size Argument

size argument
Multiplication

Overflow

overflow of

Size

size
Subtraction

Underflow

underflow of

Size

size
Truncation of

Size

size

Compass/ROSE

 

 



Can detect violations of this rule. It should look for patterns of (a op1 b) op2 c where

    • c has a bigger type than a or b
    • Neither a nor b is typecast to c's type
    • op2 is assignment or comparison
Coverity6.5OVERFLOW_BEFORE_WIDENFully
Implemented

Fortify SCA

5.0

 

Can detect violations of this rule with CERT C Rule Pack

CERT C Rules implemented in the
implemented
Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C1890, C1891, C1892, C1893, C1894, C1895, C4490, C4491, C4492


Klocwork
Include Page
Klocwork_V
Klocwork_V

PORTING.CAST.SIZE


LDRA tool suite
Include Page
LDRA_V
LDRA_V
452 SPartially implemented
PRQA QA-C
Parasoft C/C++test
Include Page
PRQA QA-C_vPRQA QA-C_v

1890
1891
1892
1893
1894
1895
4490

4491

4492

Parasoft_V
Parasoft_V

CERT_C-INT18-a
CERT_C-INT18-b
CERT_C-INT18-c

Avoid possible integer overflow in expressions in which the result is assigned to a variable of a wider integer type
Avoid possible integer overflow in expressions in which the result is compared to an expression of a wider integer type
Avoid possible integer overflow in expressions in which the result is cast to a wider integer type

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C: Rec. INT18-C

Checks for integer overflow and unsigned integer overflow (rec. fully covered)

Partially implemented

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Related Guidelines

Bibliography

[
AA. Bibliography#Dowd 06
Dowd 2006]Chapter 6, "C Language Issues"
[
AA. Bibliography#Seacord
Seacord 2013]Chapter 5, "Integer Security"

...


...

Image Modified Image Modified Image Modified