Many functions accept pointers as arguments. If the function dereferences an invalid pointer (as in rule EXP34-C. Do not dereference null pointers) or reads or writes to a pointer that does not refer to an object, the results are undefined. Typically, the program will terminate abnormally when an invalid pointer is dereferenced, but it is possible for an invalid pointer to be dereferenced , and its memory changed , without abnormal termination [Jack 2007]. Such programs can be difficult to debug because of the difficulty in determining if a pointer is valid.
One way to eliminate invalid pointers is to define a function that accepts a pointer argument and indicates whether the or not the pointer is valid or not, for some definition of valid. For example, the following function declares any pointer to be valid except NULL
.
Code Block |
---|
int valid(void *ptr) {
return (ptr != NULL);
}
|
...
The following code relies on the _etext
address, defined by the loader as the first address following the program text on many platforms, including AIX, Linux, QNX, IRIX, and Solaris. It is not POSIX-compliant, nor is it available on Windows.
Code Block |
---|
#include <stdio.h>
#include <stdlib.h>
int valid(void *p) {
extern char _etext;
return (p != NULL) && ((char*) p > &_etext);
}
int global;
int main(void) {
int local;
printf("pointer to local var valid? %d\n", valid(&local));
printf("pointer to static var valid? %d\n", valid(&global));
printf("pointer to function valid? %d\n", valid((void *)main));
int *p = (int *) malloc(sizeof(int));
printf("pointer to heap valid? %d\n", valid(p));
printf("pointer to end of allocated heap valid? %d\n", valid(++p));
free(--p);
printf("pointer to freed heap valid? %d\n", valid(p));
printf("null pointer valid? %d\n", valid(NULL));
return 0;
}
|
On a Linux platform, this program produces the following output:
Code Block |
---|
pointer to local var valid? 1
pointer to static var valid? 1
pointer to function valid? 0
pointer to heap valid? 1
pointer to end of allocated heap valid? 1
pointer to freed heap valid? 1
null pointer valid? 0
|
...
In this noncompliant code example, the incr()
function increments the value referenced by its argument. It also ensures that its argument is not a null pointer. But the pointer could still be invalid, causing the function to corrupt memory or terminate abnormally.
Code Block | ||||
---|---|---|---|---|
| ||||
void incr(int *intptr) {
if (intptr == NULL) {
/* Handle error */
}
*intptr++;
}
|
...
Code Block | ||||
---|---|---|---|---|
| ||||
void incr(int *intptr) {
if (!valid(intptr)) {
/* Handle error */
}
*intptr++;
}
|
The valid()
function can be implementation dependent and perform additional, platform-dependent checks when possible. In the worst case, the valid()
function may only perform the same null-pointer check as the noncompliant code example. However, on platforms where additional pointer validation is possible, the use of a valid()
function can provide checks.
...
CERT C++ Secure Coding Standard: MEM10-CPP. Define and use a pointer validation function
ISO/IEC 9899:19992011 Section 6.3.2.3, "Pointers"
MITRE CWE: CWE-20, "Insufficient Input Validationinput validation"
Bibliography
[Jack 2007]
[van Sprundel 2006]
...