You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 13 Next »

Many functions accept pointers as arguments. If the function dereferences an invalid pointer (see [EXP34-C. Ensure a null pointer is not dereferenced]), 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 the invalid pointer is dereferenced, but it is possible for an invalid pointer to be dereferenced, and its memory changed, without abnormal termination [[Jack 07]]. 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 if the pointer is valid or not, for some definition of valid. For example, the following function declares any pointer to be valid except NULL.

int valid(void *ptr) {
  return (ptr != NULL);
}

Some platforms have platform-specific pointer validation tools.

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.

#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;
  int *p;

  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));

  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++));
  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:

pointer to local var invalid? 1
pointer to static var invalid? 1
pointer to function invalid? 0
pointer to heap invalid? 1
pointer to end of allocated heap invalid? 1
pointer to freed heap invalid? 1
null pointer invalid? 0

The valid() function does not guarantee validity (it only identifies null pointers and pointers to functions as invalid), but it can be used to catch a substantial number of problems that might otherwise go undetected.

Non-Compliant Code Example

This function increments the value pointed to 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 terminate abnormally.

void incr(int *intptr) {
  if (intptr == NULL) {
    /* handle error */
  }
  *intptr++;
}

Compliant Solution

By using the valid() function defined above, the function is less likely to dereference an invalid pointer or write to memory that is outside the bounds of a valid object.

void incr(int *intptr) {
  if (!valid(intptr)) {
    /* handle error */
  }
  *intptr++;
}

Compliant Solution (assert)

Because invalid pointers are often indicative of a bug defect in the program, the assert() macro can be used to terminate immediately if an invalid pointer is discovered (see MSC11-A. Incorporate diagnostic tests using assertions).

#include <assert.h>

void incr(int *intptr) {
  assert(valid(intptr));
  *intptr++;
}

Risk Assessment

A pointer validation library can be used to identify and so prevent the execution of vulnerable code.

Failure to clear memory can result in leaked information. Occasionally, it can also lead to buffer overflows if the program falsely assumes that a null-termination byte is present.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

MEM10-A

high

unlikely

high

P3

L3

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

References

[[ISO/IEC 9899:1999]] Section 6.3.2.3, "Pointers"
[[Jack 07]]
[[van Sprundel 06]]


MEM09-A. Do not assume memory allocation routines initialize memory      08. Memory Management (MEM)      

  • No labels