Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Null Pointer Dereference

Null Pointer Dereference is a bug caused by dereferencing a null pointer. This is generally characterised by a process failure, which can create an availability risk in the context of DoS-type attacks (CWE-476).

A simple example is the code below:

#include <stdlib.h>

int main(void) {
    int* p = NULL;
    *p = 42; // "Segmentation fault" here, since we're dereferencing NULL.
    return EXIT_SUCCESS;
}

Detection and Debugging Tools

To detect this bug, it is possible to use static code analysis tools such as Clang Static Analyzer, Cppcheck or Infer (for the C language) or fuzzers such as AFL++ (for the C language), although these tools do not detect all occurrences of the problem.

In the event of a failure, it is therefore also necessary to have debugging tools such as GDB or Valgrind (for the C language), that can identify the instruction causing the problem.

A more drastic solution to address this bug is to use languages that simply do not allow the use of NULL values or a NULL variable to be dereferenced, such as Kotlin, Zig, or Rust.

Exercise

The exercise program contains the implementation of a linked list and, unfortunately, it doesn’t work. Your goal is:

  1. to find the bug using debugging tools (GDB and/or Valgrind like real pros, no printf);
  2. and to fix it.

Please refer to the Practical Sessions Setup if not done yet.

The Case of Rust

In Rust, this bug is not possible because all references must point to a valid variable, so the concept of NULL does not exist in Rust. To be exact, the concept of NULL exists, but only in unsafe mode and for extremely specific cases such as using FFIs, in the standard library, etc. Over 99% of the time, it is possible and desirable to stay in Rust’s safe mode and use alternatives of NULL such as the Option enum.

Here is an example of Rust code that shows this feature:

fn main() {
    let mut p: Option<i32> = None;
    p = Some(1); // No segfault, yay.
}

It is a safe alternative to the C code showed in the intro.