...
Code Block | ||
---|---|---|
| ||
struct big { unsigned long long ull_1; /* typically 8 bytes */ unsigned long long ull_2; /* typically 8 bytes */ unsigned long long ull_3; /* typically 8 bytes */ int si_4; /* typically 4 bytes */ int si_5; /* typically 4 bytes */ }; /* ... */ size_t skip = offsetof(struct big, ull_2); struct big *s = (struct big *)malloc(sizeof(struct big)); if (!s) { /* Handle malloc() error */ } memset((char *)s + skip, 0, sizeof(struct big) - skip); /* ... */ free(s); s = NULL; |
Automated Detection
How long is 4 yards plus 3 feet? It is obvious from elementary arithmetic that any answer involving '7' is wrong, as the student did not take the units into account. The right method is to convert both numbers to reflect the same units.
The examples in this rule both reflect the Right Way and the Wrong Way to handle additions of numbers representing different things (either single bytes or multibyte data structures). The NCCEs just add the numbers without regard to units, whereas the CCEs convert one number to the appropriate unit of the other number, by using typecasts.
ROSE could catch both NCCE's by searching for pointer arithmetic expressions involving different units. The 'different units' is the tricky part, but one can try to identify an expression's units using some simple heuristics:
- A pointer to a 'foo' object has 'foo' as the unit.
- A pointer to char* has unit 'byte'.
- Any sizeof or offsetof expression also has unit 'byte'.
- Any variable used in an index to an array of foo objects (eg foovariable) has 'foo' as the unit.
In addition to pointer arithmetic expressions, one could also hunt for array index expressions, as arrayindex is merely shorthand for 'array + index'. But I suspect programmers will be more conscientious about using [] with correct units rather than using pointer arithmetic.
Risk Assessment
Failure to understand and properly use pointer arithmetic can allow an attacker to execute arbitrary code.
...