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

Compare with Current View Page History

« Previous Version 3 Next »

Many library functions take pointers as arguments. If the pointer passed to a library function does not refer to valid memory, the results are undefined (see [EXP34-C. Ensure a null pointer is not dereferenced]). Typically the program will terminate abnormally when the invalid pointer is dereferenced, but it is possible, and quite common, for an invalid pointer to be dereferenced, and its memory changed, without abnormal termination [[Jack 07]]. Such programs can be very difficult to debug due to the difficulty of determining the pointer's lack of validity.

One source of prevention of invalid pointers would be a function that could take a pointer and indicate if the pointer is 'valid' or not, for some definition of valid. For instance, here is a function that declares any pointer to be valid except NULL.

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

Some platforms will have platform-specific pointer validation tools.

The following code relies on the _etext address, which is provided by 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 invalid(void* p) {
  extern char _etext;
  return (p == NULL) || ((char*) p < &_etext);
}


int global;

int main(void) {
  int local;
  void *p = &local;
  int* q = (int*) malloc(sizeof(int));
  printf("pointer to local var invalid? %d\n", invalid(p));
  p = &global;
  printf("pointer to static var invalid? %d\n", invalid(p));
  p = (void*) main;
  printf("pointer to function invalid? %d\n", invalid(p));

  printf("pointer to heap invalid? %d\n", invalid(q));
  q++;
  printf("pointer to end of allocated heap invalid? %d\n", invalid(q));
  q--;
  free(q);
  printf("pointer to freed heap invalid? %d\n", invalid(q));
  q = NULL;
  printf("null pointer invalid? %d\n", invalid(q));

  return 0;
}

On a Linux platform, this program produces the following output:

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

As you can see, the invalid() function is not perfect; it only identifies NULL pointers and pointers to functions as invalid.

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, thus causing the function to corrupt memory, or possibly terminate abnormally.

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

Compliant Solution

By using the invalid() function defined above, the function is less likely to modify memory outside its bounds.

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

Compliant Solution (assert)

Since invalid pointers are often indicative of a bug in the program, one can use the assert() macro to terminate immediately if an invalid pointer is discovered.

#include <assert.h>

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

Risk Assessment

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

Failure to clear memory can result in leaked information. Occasionally, it can also lead to buffer overflows when programmers assume, for example, a NULL termination byte is present when it is not.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

MEM10-A

low

unlikely

high

P1

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