...
This noncompliant code example assigns a value greater than the size number of bytes of available memory to n
, which is then passed to memset()
:
...
For calls that take a pointer and an integer size, the given size should not be greater than the element count of the pointer. This compliant solution ensures that the value of n
is not greater than the size number of bytes of the dynamic memory pointed to by the pointer p
:
Code Block | ||
---|---|---|
| ||
#include <stdlib.h> #include <string.h> void f1(size_t nchars) { char *p = (char *)malloc(nchars); /* ... */ const size_t n = nchars; /* ... */ memset(p, 0, n); } |
Noncompliant Code Example (Pointer + Integer)
In this noncompliant code example, the element count of the array a
is ARR_SIZE
elements. Because memset() expects a byte count, the size of the array is scaled incorrectly by sizeof(int)
instead of sizeof(float)
, which can form an invalid pointer on architectures where sizeof(int) != sizeof(float)
.
...
In this compliant solution, the element count required by memset
is ()
is properly calculated without resorting to scaling.
...
Code Block | ||
---|---|---|
| ||
#include <string.h> void f4(char p[], const char *q) { const size_t n = sizeof(p); if ((memcpy(p, q, n)) == p) { /* ... */ } } |
This example is also a violation of violates ARR01-C. Do not apply the sizeof operator to a pointer when taking the size of an array.
...
Code Block | ||
---|---|---|
| ||
#include <string.h>
void f4(char p[], const char *q, size_t size_p) {
const size_t n = size_p;
if ((memcpy(p, q, n)) == p) {
/* ... */
}
} |
Noncompliant Code Example (One Pointer + Two Integers)
In this This noncompliant code example , the allocates a variable number of objects of type struct obj
. The function checks that numObjs
is small enough to prevent wrapping, in compliance with INT30-C. Ensure that unsigned integer operations do not wrap. The size of struct obj
is is assumed to be eight bytes to account for padding. However However, the padding is dependent on the target architecture as well as compiler settings, so this object size may be the incorrect size of the object, which then yields the incorrect. This would then yield an incorrect element count.
Code Block | ||
---|---|---|
| ||
#include <stdint.h> #include <stdio.h> struct obj { char c; int i; }; void func(FILE *f, struct obj *objs, size_t numObjs) { const size_t obj_size = 8; if (numObjs > (SIZE_MAX / obj_size) || numObjs != fwrite(objs, obj_size, numObjs, f)) { /* Handle error */ } } |
...
Compliant Solution (One Pointer + Two Integers)
For calls that take a pointer and two integers, generally accept one integer representing the size of an individual object, and a second integer representing the number of objects in the array. The resulting product of the two integers should not be greater than the element count of the pointer were it expressed as an unsigned char *
. See INT30-C. Ensure that unsigned integer operations do not wrap for more information.This compliant solution uses the sizeof
operator to correctly provide the object size.
Code Block | ||
---|---|---|
| ||
#include <stdint.h> #include <stdio.h> struct obj { char c; int i; }; void func(FILE *f, struct obj *objs, size_t numObjs) { if (numObjs > (SIZE_MAX / sizeof(*objs)) || numObjs != fwrite(objs, sizeof(*objs), numObjs, f)) { /* Handle error */ } } |
...
Depending on the library function called, the an attacker may be able to use a heap or stack overflow vulnerability to run arbitrary code.
...