All integer values originating from untrusted sources should be evaluated to determine if there are they have identifiable upper and lower bounds. If so, these limits should be enforced by the interface. Restricting the input of excessively large or small integers helps prevent overflow, truncation, and other type range errors. Furthermore, it is easier to find and correct input problems than it is to trace internal errors back to faulty inputs.
...
In this noncompliant code example, length
is the value of a user-defined (and thus potentially untrusted) environment variable whose value is used to determine the size of a dynamically allocated array, table
. In compliance with INT30-C. Ensure that unsigned integer operations do not wrap, the code prevents unsigned integer wrapping but doesn't does not impose any upper bound on the size of the array, making it possible for the user to cause the program to use an excessive amount of memory.
Code Block |
---|
|
char** create_table(void) {
const char* const lenstr = getenv("TABLE_SIZE");
const size_t length = lenstr ? strtoul(lenstr, NULL, 10) : 0;
if (length > SIZE_MAX / sizeof(char *))
return NULL; /* indicateIndicate error to caller */
const size_t table_size = length * sizeof(char *);
char** const table = (char **)malloc(table_size);
if (table == NULL)
return NULL; /* indicateIndicate error to caller */
/* initializeInitialize table... */
return table;
}
|
Because length
is user controlled, the value can result in a large block of memory being allocated or can cause the call to malloc()
to fail. Depending on how error handling is implemented, this it may result in a denial-of-service attack or other error.
Compliant Solution
...
Code Block |
---|
|
enum { MAX_TABLE_LENGTH = 256 };
char** create_table(void) {
const char* const lenstr = getenv("TABLE_SIZE");
const size_t length = lenstr ? strtoul(lenstr, NULL, 10) : 0;
if (length == 0 || length > MAX_TABLE_LENGTH)
return NULL; /* indicateIndicate error to caller */
const size_t table_size = length * sizeof(char *);
char** const table = (char **)malloc(table_size);
if (table == NULL)
return NULL; /* indicateIndicate error to caller */
/* initializeInitialize table... */
return table;
}
|
...
Code Block |
---|
|
const char *table[] = { "black", "white", "blue", "green" };
const char *set_background_color(void) {
int color_index;
GET_TAINTED_INTEGER(int, color_index);
const char *color = table[color_index]; /* violationViolation */
/* ... */
return color;
} |
...
Code Block |
---|
|
enum { MAX_COLOR_INDEX = 3 };
const char *table[] = { "black", "white", "blue", "green" };
const char *set_background_color(void) {
int color_index;
GET_TAINTED_INTEGER(int, color_index);
if (color_index < 0 || colo_index > MAX_COLOR_INDEX)
return NULL; /* indicateIndicate error to caller */
const char *color = table[color_index];
/* ... */
return color;
} |
...
Bibliography
...