...
This noncompliant code example assigns a value greater than the size of available memory to n
, which is then passed to memset()
:
Code Block | ||
---|---|---|
| ||
#include <stdlib.h> #include <string.h> void f1(size_t nchars) { char *p = (char *)malloc(nchars); const size_t n = nchars + 1; memset(p, 0, n); /* ... */ } |
Compliant Solution
This compliant solution ensures that the value of n
is not greater than the size of the dynamic memory pointed to by the pointer p
:
Code Block | ||
---|---|---|
| ||
#include <stdlib.h> #include <string.h> void f1(size_t nchars, size_t val) { char *p = (char *)malloc(nchars); const size_t n = val; if (nchars < n) { /* Handle Error */ } else { memset(p, 0, n); } /* ... */ } |
Noncompliant Code Example
In this noncompliant code example, the effective type of *p
is float
, and the derived type of the expression n
is int
. This is calculated using the first rule from TS 17961's definition of derived types (see Section 4, "Definitions" [ISO/IEC TS 17961]). Because n
contains the result of a sizeof
expression, its derived type is equal to the type of the operand, which is int
.
Code Block | ||
---|---|---|
| ||
void f2(#include <string.h> void f2() { const size_t ARR_SIZE = 4; float a[ARR_SIZE]; const size_t n = sizeof(int) * ARR_SIZE; void *p = a; memset(p, 0, n); /* ... */ } |
Note: Although it is noncompliant, this code has no ill effects on architectures where sizeof(int)
is equal to sizeof(float)
.
...
In this compliant solution, the derived type of n
is also float
:
Code Block | ||
---|---|---|
| ||
#include <string.h> void f2() { const size_t ARR_SIZE = 4; float a[ARR_SIZE]; const size_t n = sizeof(float) * ARR_SIZE; void *p = a; memset(p, 0, n); /* ... */ } |
Noncompliant Code Example
In this noncompliant code example, the size of n
could be greater than the size of *p
. Also, the effective type of *p
(int
) is different from the effective type of *q
(float
).
Code Block | ||
---|---|---|
| ||
#include <string.h> void f3(int *a) { float b = 3.14; const size_t n = sizeof(b); void *p = a; void *q = &b; memcpy(p, q, n); /* ... */ } |
Note: Although it is noncompliant, this code does not constitute a vulnerability on implementations where sizeof(int)
is equal to sizeof(float)
.
...
This compliant solution ensures that the value of n
is not greater than the minimum of the effective sizes of *p
and *q
and that the effective types of the two pointers are identical (float
):
Code Block | ||
---|---|---|
| ||
#include <string.h> void f3(float *a, size_t val) { float b = 3.14; const size_t n = val; void *p = a; void *q = &b; if( (n > sizeof(a)) || (n > sizeof(b)) ) { /* Handle error */ } else { memcpy(p, q, n); /* ... */ } } |
Noncompliant Code Example
In this noncompliant code example, the value of n
is greater than the size of T
, that is, sizeof(wchar_t)
. But the derived type of expression n
(wchar_t *
) is not the same as the type of T
because its derived type will be equal to the type of p
, which is wchar_t*
. The derived type of n
is calculated using the first rule from TS 17961's definition of derived types (see Section 4, "Definitions" [ISO/IEC TS 17961]). Because n
here is a sizeof
expression, its derived type is equal to the type of the operand (p
), which is wchar_t *
.
Code Block | ||
---|---|---|
| ||
#include <stdlib.h>
#include <wchar.h>
wchar_t *f4() {
const wchar_t *p = L"Hello, World!";
const size_t n = sizeof(p) * (wcslen(p) + 1);
wchar_t *q = (wchar_t*) malloc(n);
return q;
}
|
...
This compliant solution ensures that the derived type of n
(wchar_t
) is the same as the type of T
(wchar_t
) and that the value of n
is not less than the size of T
:
Code Block | ||
---|---|---|
| ||
#include <stdlib.h>
#include <wchar.h>
wchar_t *f4() {
const wchar_t *p = L"Hello, World!";
const size_t n = sizeof(wchar_t) * (wcslen(p) + 1);
wchar_t *q = (wchar_t*) malloc(n);
return q;
}
|
...
In this noncompliant example, a diagnostic is required because the value of n
is not computed correctly, allowing a possible write past the end of the object referenced by p
:
Code Block | ||
---|---|---|
| ||
#include <string.h> void f4(char p[], const char *q) { const size_t n = sizeof(p); if ((memcpy(p, q, n)) == p) { /* violation */ /* ... */ } /* ... */ } } } |
Compliant Solution
This compliant solution ensures that n
is equal to the size of the character 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) { /* ... */ } /* ... */ } |
Risk Assessment
Depending on the library function called, the attacker may be able to use a heap overflow vulnerability to run arbitrary code.
...
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
PRQA QA-C |
| 2931 | Fully implemented |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
C Secure Coding Standard | API00-C. Functions should validate their parameters |
ISO/IEC TS 17961 (Draft) | Forming invalid pointers by library functions [libptr] |
...