...
Code Block |
---|
|
char *copy(size_t n, char const *str) {
int i;
char *p = (char *)malloc(n);
if (p == NULL) {
/* Handle malloc failure */
}
for ( i = 0; i < n; ++i ) {
p[i] = *str++;
}
return p;
}
/* ... */
char str[] = "hi there";
char *p = copy(9sizeof(str), "hi there"str);
|
Signed integer overflow causes undefined behavior. The following are two possible conditions under which this code constitutes a serious vulnerability:
...
Code Block |
---|
|
char *copy(rsize_t n, char const *str) {
rsize_t i;
char *p;
if (n > RSIZE_MAX) {
/* Handle unreasonable object size error */
}
p = (char *)malloc(n);
if (p == NULL) {
/* Handle malloc failure */
}
for ( i = 0; i < n; ++i ) {
p[i] = *str++;
}
return p;
}
/* ... */
char str[] = "hi there";
char *p = copy(sizeof(9str), "hi there"str);
|
Non-Compliant Code Example
In this non-compliant code example, an integer overflow is specifically looked for by checking whether length + 1 == 0
(that is, integer wrap around has occurred). If the test passes, a wrapper to malloc()
is called to allocate the appropriate data block. When sizeof(int) == sizeof(long)
UINT_MAX == ULONG_MAX
, this code runs as expected, but if sizeof(long) > sizeof(int)
ULONG_MAX > UINT_MAX
, an integer overflow can occur when length
is passed in to alloc()
because the result is truncated down to an unsigned int
.
Code Block |
---|
|
void *alloc(unsigned int blocksize) {
return malloc(blocksize);
}
int read_counted_string(int fd) {
unsigned long length;
unsigned char *data;
if (read_integer_from_network(fd, &length) < 0) {
return -1;
}
if (length + 1 == 0ULONG_MAX) {
/* handle integer overflow */
}
data = (unsigned char*)alloc(length + 1);
if (read_network_data(fd, data, length) < 0) {
free(data);
return -1;
}
data[length] = '\0';
/* ... */
free( data);
return 0;
}
|
...
Code Block |
---|
|
void *alloc(rsize_t blocksize) {
if (blocksize > RSIZE_MAX) {
/* Handle error */
}
return malloc(blocksize);
}
int read_counted_string(int fd) {
rsize_t length;
unsigned char *data;
if (read_integer_from_network(fd, &length) < 0) {
return -1;
}
if (length + 1 == 0RSIZE_MAX) {
/* handle integer overflow */
}
data = (unsigned char*)alloc(length + 1);
if (read_network_data(fd, data, length) < 0) {
free(data);
return -1;
}
data[length] = '\0';
/* ... */
free( data);
return 0;
}
|
...