You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 53 Next »

In C89 (and historical K&R implementations), the meaning of the remainder operator for negative operands was implementation defined. This was changed in the C99 standard [ISO/IEC 9899-1999].

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

According to C99

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.

and

When integers are divided, the result of the / operator is the algebraic quotient with any fractional part discarded. If the quotient a/b is representable, the expression (a/b)*b + a%b shall equal a.

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

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

 17 %  3  ->  2
 17 % -3  ->  2
-17 %  3  -> -2
-17 % -3  -> -2

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

Noncompliant Code Example

In this noncompliant 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 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.

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.

Noncompliant Code Example

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

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 rsize_t or size_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.

Compliant Solution (Unsigned Types)

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' argument with the mathematical result, and we return nonzero only if the operation succeeds.

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

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

INT10-C

low

unlikely

high

P1

L3

Automated Detection

Tool

Version

Checker

Description

Fortify SCA

V. 5.0

 

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

Compass/ROSE

 

 

could detect the specific NCCE. 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 introduce many false positives

Related Vulnerabilities

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

Related Guidelines

CERT C++ Secure Coding Standard: INT10-CPP. Do not assume a positive remainder when using the % operator

ISO/IEC 9899-1999 Section 6.5.5, "Multiplicative operators"

The CERT Oracle Secure Coding Standard for Java: NUM15-J. Ensure that division and modulo operations do not result in divide-by-zero errors

MITRE CWE: CWE-682, "Incorrect Calculation"

MITRE CWE: CWE-129, "Unchecked Array Indexing"

Bibliography

[Beebe 2005]
[Microsoft 2007] C Multiplicative Operators
[Sun 2005] Appendix E, "Implementation-Defined ISO/IEC C90 Behavior"


      04. Integers (INT)       INT11-C. Take care when converting from pointer to integer or integer to pointer

  • No labels