...
This noncompliant code example shows a function insert_in_table()
that has two int
paramters, pos
and value
, both of which can be influenced by data originating from untrusted sources. The function uses a global variable table
to determine if storage has been allocated for an array of 100 integer elements and allocates the memory if it has not already been allocated.
Code Block |
---|
|
enum { TABLESIZE = 100 };
int *table = NULL;
int insert_in_table(int pos, int value){
if (!table) {
table = new int[TABLESIZE];
}
if (pos >= TABLESIZE) {
return -1;
}
table[pos] = value;
return 0;
}
|
...
In this compliant solution, the parameter pos
is declared as size_t
, which prevents passing of negative arguments (see INT01-CPP. Use rsize_t or size_t for all integer values representing the size of an object).
Code Block |
---|
|
enum { TABLESIZE = 100 };
int *table = NULL;
int insert_in_table(size_t pos, int value){
if (!table) {
table = new int[TABLESIZE];
}
if (pos >= TABLESIZE) {
return -1;
}
table[pos] = value;
return 0;
}
|
...
Wiki Markup |
---|
Specialized function templates can be used to define functions that accept an array of a generic type {{T}} of size {{n}}. The compiler can perform template argument deduction for function templates to properly deduce both the type and size. This compliant solution defines a function template for a function {{clear()}} that takes a template parameter {{array\[\]}} of {{T}} elements and an actual length parameter of type {{size_t}}. This is not particularly useful yet, as we have already seen that passing an array with an explicit size parameter is a common (but error prone) idiom. However, you can also define a specialization of the function template that includes a template parameter {{n}} of type {{size_t}} in addition to the original type parameter. The inline function {{clear()}} has one parameter: an array of type {{T}} elements of fixed length {{n}}. |
Code Block |
---|
|
template <typename T>
void clear(T array[], size_t n) {
for (size_t i = 0; i < n; ++i) {
array[i] = 0;
}
}
template <typename T, size_t n>
inline void clear(T (&array)[n]) {
clear(array, n);
}
int int_array[12];
clear(int_array); // deduce T is int, and that n is 12
|
...
The above code examples perform the same when working with vectors.
Code Block |
---|
|
vector<int> table;
int insert_in_table(int pos, int value){
if (pos >= table.size()) {
return -1;
}
table[pos] = value;
return 0;
}
|
...
In this compliant solution, the parameter pos
is declared as size_t
, which prevents passing of negative arguments (see INT01-CPP. Use rsize_t or size_t for all integer values representing the size of an object).
Code Block |
---|
|
vector<int> table;
int insert_in_table(size_t pos, int value){
if (pos >= table.size()) {
return -1;
}
table[pos] = value;
return 0;
}
|
...
In this compliant solution, access to the vector is accomplished with the at()
method. This method provides bounds checking, throwing an out_of_range
exception if pos
is not a valid index value.
Code Block |
---|
|
vector<int> table;
int insert_in_table(size_t pos, int value){
table.at(pos) = value;
return 0;
}
|
...