...
This noncompliant code example shows a function, insert_in_table()
, that has two int
parameters, pos
and value
, both of which can be influenced by data originating from untrusted sources. The function performs a range check to ensure that pos
does not exceed the upper bound of the array, specified by table_size
tableSize
, but fails to check the lower bound. Because pos
is declared as a (signed) int
, this parameter can assume a negative value, resulting in a write outside the bounds of the memory referenced by table
.
Code Block |
---|
|
#include <cstddef>
void insert_in_table(int *table, std::size_t table_sizetableSize, int pos, int value) {
if (pos >= table_sizetableSize) {
// Handle error
return;
}
table[pos] = value;
} |
...
Code Block |
---|
|
#include <cstddef>
void insert_in_table(int *table, std::size_t table_sizetableSize, std::size_t pos, int value) {
if (pos >= table_sizetableSize) {
// Handle error
return;
}
table[pos] = value;
} |
...
Code Block |
---|
|
#include <cstddef>
#include <new>
void insert_in_table(int *table, std::size_t table_sizetableSize, std::size_t pos, int value) { // #1
if (pos >= table_sizetableSize) {
// Handle error
return;
}
table[pos] = value;
}
template <std::size_t N>
void insert_in_table(int (&table)[N], std::size_t pos, int value) { // #2
insert_in_table(table, N, pos, value);
}
void f() {
// Exposition only
int table1[100];
int *table2 = new int[100];
insert_in_table(table1, 0, 0); // Calls #2
insert_in_table(table2, 0, 0); // Error, no matching function call
insert_in_table(table1, 100, 0, 0); // Calls #1
insert_in_table(table2, 100, 0, 0); // Calls #1
delete [] table2;
} |
...
Code Block |
---|
|
#include <iterator>
template <typename ForwardIterator>
void f_imp(ForwardIterator Bb, ForwardIterator Ee, int Valval, std::forward_iterator_tag) {
do {
*Bb++ = Valval;
} while (Bb != Ee);
}
template <typename ForwardIterator>
void f(ForwardIterator Bb, ForwardIterator Ee, int Valval) {
typename std::iterator_traits<ForwardIterator>::iterator_category Catcat;
f_imp(Bb, Ee, Valval, Catcat);
} |
Compliant Solution
This compliant solution tests for iterator validity before attempting to dereference the forward iterator:
Code Block |
---|
|
#include <iterator>
template <typename ForwardIterator>
void f_imp(ForwardIterator Bb, ForwardIterator Ee, int Valval, std::forward_iterator_tag) {
while (Bb != Ee) {
*Bb++ = Valval;
}
}
template <typename ForwardIterator>
void f(ForwardIterator Bb, ForwardIterator Ee, int Valval) {
typename std::iterator_traits<ForwardIterator>::iterator_category Catcat;
f_imp(Bb, Ee, Valval, Catcat);
} |
Risk Assessment
Using an invalid array or container index can result in an arbitrary memory overwrite or abnormal program termination.
...