...
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.
| Code Block | ||||
|---|---|---|---|---|
| ||||
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;
}
}
|
...
Taking the absolute value of the modulo operation returns a positive value:
| Code Block | ||||
|---|---|---|---|---|
| ||||
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;
}
}
|
...
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.
| Code Block | ||||
|---|---|---|---|---|
| ||||
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;
}
}
|
...