Do not make assumptions about the sign of the remainder when using the % operator.
In C89 (and historical K&R implementations), the meaning of the remainder operator for negative arguments was implementation-defined, but was fixed in the C99 Standard.
Because not all C-compilers are strictly C99-conforming, you can not 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.When integers are divided, the result of the
/operator is the algebraic quotient with any fractional part discarded. If the quotienta/bis representable, the expression(a/b)*b + a%bshall equala.
Discarding the fractional part of the remainder is often called "truncation toward zero".
The C99 definition of % 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).
Non-Compliant Coding Example
In this non-compliant 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 non-compliant code example also violates [[INT01-A. Use rsize_t or size_t for all integer values representing the size of an object]].
Compliant Solution
To provide a true (never negative) modulo operation, use the imod() ("integer modulo") inline function:
/* modulo function giving non-negative result */
inline int imod(int i, int j) {
return (i % j) < 0 ? (i % j) + (j < 0 ? -j : j) : i % j;
}
Risk Assessment
Recommendation |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
|---|---|---|---|---|---|
INT10-A |
1 (low) |
1 (unlikely) |
2 (medium) |
P2 |
L3 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[[Beebe 05]] Nelson H. F. Beebe Re: Remainder ( % ) operator and GCC
2005.
[[ISO/IEC 9899-1999]] Section 6.5.5, "Multiplicative operators"
[[Microsoft 07]] C Multiplicative Operators![]()
[[Sun 05]] C User's Guide Sun Studio 11 819-3688-10 http://docs.sun.com/source/819-3688/
. 2005. Appendix E, "Implementation-Defined ISO/IEC C90 Behavior"![]()
INT09-A. Ensure enumeration constants map to unique values 04. Integers (INT) INT11-A. Do not make assumptions about the layout of bit-field structures