Versions Compared

Key

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

Wiki MarkupIn C89 (and historical K&R [implementations|BB. Definitions#implementation]), the meaning of the remainder operator for negative operands was [implementation -defined|BB. Definitions#implementation defined behavior]. This was changed in the C99 standard \[[ISO/IEC 9899-1999|AA. Bibliography#ISO/IEC 9899-1999]\].. This behavior was changed in C99, and the change remains in C11.

Because not all C compilers are strictly C99 C-conforming, you programmers cannot rely on the behavior of the % operator if you they need to run on a wide range of platforms with many different compilers.According to C99

The C Standard, subclause 6.5.5 [ISO/IEC 9899:2011], states:

The result of the / operator is the quotient from the division of the first operand by the second; the result of the % operator is the remainder. In both operations, if the value of the second operand is zero, the behavior is undefined.

...

Discarding the fractional part of the remainder is often called truncation toward zero.

The C99 C definition of the % operator implies the following behavior:

Code Block

 1711 %  35  ->  21
 1711 % -35  ->  21
-1711 %  35  -> -21
-1711 % -35  -> -21

The result has the same sign as the dividend (the first operand in the expression).

Noncompliant Code Example

In this noncompliant code example, the insert() function adds values to a buffer in a modulo fashion, that is, by inserting values at the beginning of the buffer once the end is reached. However, both size and index are declared as int and , consequently , not are not guaranteed to be positive. Depending on the implementation and on the sign of size and index, the result of (index + 1) % size may be negative, resulting in a write outside the bounds of the list array.

Code Block
bgColor#FFCCCC
langc

int insert(int index, int *list, int size, int value) {
  if (size != 0) {
    index = (index + 1) % size;
    list[index] = value;
    return index;
  }
  else {
    return -1;
  }
}

This code also violates recommendation ERR02-C. Avoid in-band error indicators.

...

Taking the absolute value of the modulo operation returns a positive value:

Code Block
bgColor#FFCCCC
langc

int insert(int index, int *list, int size, int value) {
  if (size != 0) {
    index = abs((index + 1) % size);
    list[index] = value;
    return index;
  }
  else {
    return -1;
  }
}

However, this noncompliant code example violates recommendation INT01-C. Use rsizesize_t or sizersize_t for all integer values representing the size of an object. There is also a possibility that (index + 1) could result in a signed integer overflow in violation of rule INT32-C. Ensure that operations on signed integers do not result in overflow.

...

The most appropriate solution in this case is to use unsigned types to eliminate any possible implementation-defined behavior, as in this compliant solution. For compliance with recommendation ERR02-C, we fill a 'result' . Avoid in-band error indicators, this solution fills a result argument with the mathematical result , and we return returns nonzero only if the operation succeeds.

Code Block
bgColor#ccccff
langc

int insert(size_t* result, size_t index, int *list, size_t size, int value) {
  if (size != 0 && size != SIZE_MAX) {
    index = (index + 1) % size;
    list[index] = value;
    *result = index;
    return 1;
  }
  else {
    return 0;
  }
}

Risk Assessment

Incorrectly assuming that the result of the remainder operator for signed operands will always be positive can lead to an out-of-bounds memory accessor other flawed logic.

Recommendation

Severity

Likelihood

Remediation Cost

Detectable

Repairable

Priority

Level

INT10-C

High

low

Unlikely

unlikely

No

high

No

P1

P3

L3

Automated Detection

Tool

Version

Checker

Description

Section

Fortify SCA

Section

V. 5.0

 

Section

can detect violations of this recommendation with the CERT C Rule Pack

section

Compass/ROSE

 

 

Sectioncould



Could detect the specific

NCCE

noncompliant code example. It could identify when the result of a % operation might be negative

,

and flag usage of that result in an array index. It could

,

conceivably flag usage of any such result without first checking that the result is positive,

but this will most likely

but it would likely introduce many false positives

Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C3103
LDRA tool suite
Include Page
LDRA_V
LDRA_V

584 S

Fully implemented

Parasoft C/C++test
Include Page
Parasoft_V
Parasoft_V

CERT_C-INT10-a

The operands of the remainder operator '%' should be of unsigned integer types

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C: Rec. INT10-C


Checks for tainted modulo operand (rec. fully covered)


Related Vulnerabilities

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

Related Guidelines

...

...

...

...

...

...

...

...

...

Incorrect

...

calculation

...

...

...

Unchecked

...

array indexing

Bibliography

...

...

[

...

...


...

Image Added Image Added Image Added|AA. Bibliography#Beebe 05]\] \[[Microsoft 2007|AA. Bibliography#Microsoft 07]\] [C Multiplicative Operators|http://msdn2.microsoft.com/en-us/library/efa0csed(VS.80).aspx] \[[Sun 2005|AA. Bibliography#Sun 05]\] [Appendix E, "Implementation-Defined ISO/IEC C90 Behavior"|http://docs.sun.com/source/819-3688/c90.implementation.app.html]Image Removed      04. Integers (INT)       INT11-C. Take care when converting from pointer to integer or integer to pointer