...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdlib.h> #include <string.h> enum { SIG_DESC_SIZE = 32 }; typedef struct { char sig_desc[SIG_DESC_SIZE]; } signal_info; void func(size_t num_of_records, size_t temp_num, const char *tmp2, size_t tmp2_size_bytes) { signal_info *start = (signal_info *)calloc(num_of_records, sizeof(signal_info)); if (tmp2 == NULL) { /* Handle signal_infoerror *point/ =} startelse +if (temp_num - 1; > num_of_records) { /* Handle error */ } else if (tmp2 == NULL_size_bytes < SIG_DESC_SIZE) { /* Handle error */ } signal_info *point = start + temp_num - 1; memcpy(point->sig_desc, tmp2, SIG_DESC_SIZE); point->sig_desc[SIG_DESC_SIZE) - 1] = '\0'; /* ... */ free(start); } |
When calloc()
fails, it returns a null pointer that is assigned to start
. If start
is null, an attacker can provide a value for temp_num
that, when scaled by sizeof(signal_info)
, references a writable address to which control is eventually transferred. The contents of the string referenced by tmp2
can then be used to overwrite the address, resulting in an arbitrary code execution vulnerability.
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdlib.h> #include <string.h> enum { SIG_DESC_SIZE = 32 }; typedef struct { char sig_desc[SIG_DESC_SIZE]; } signal_info; void func(size_t num_of_records, size_t temp_num, const char *tmp2) { signal_info *point;, size_t tmp2_size_bytes) { signal_info *start = (signal_info *)calloc(num_of_records, sizeof(signal_info)); if (start == NULL) { /* Handle allocation error */ } else if (tmp2 == NULL) { /* Handle error */ sizeof(signal_info)); } else if (start == NULLtemp_num > num_of_records) { /* Handle allocation error */ } else if (tmp2 == NULL_size_bytes < SIG_DESC_SIZE) { /* Handle error */ } signal_info *point = start + temp_num - 1; memcpy(point->sig_desc, tmp2, SIG_DESC_SIZE); point->sig_desc[ SIG_DESC_SIZE - 1] = '\0'; /* ... */ free(start); } |
Noncompliant Code Example (realloc()
)
...