Skip to content

Fix null pointer dereference on malloc failure in registration - #698

Open
hirorogo wants to merge 1 commit into
OpenKinect:masterfrom
hirorogo:fix/registration-malloc-null-check
Open

hirorogo wants to merge 1 commit into
OpenKinect:masterfrom
hirorogo:fix/registration-malloc-null-check

Conversation

@hirorogo

@hirorogo hirorogo commented Mar 31, 2026 •

Copy link
Copy Markdown

Summary

freenect_init_registration_table() in src/registration.c calls malloc() twice (lines 289-290) to allocate regtable_dx and regtable_dy, then immediately passes the results to memset() (lines 291-292) without checking for NULL. If either allocation fails, memset() dereferences a null pointer, causing a segfault.

Fix

  • Added a NULL check after each malloc() call
  • If the first allocation fails, return immediately
  • If the second allocation fails, free the first allocation before returning
  • This is a minimal, safe fix that prevents the null pointer dereference

PoC

#include <cstdio>
#include <cstdlib>
#include <cstring>

// Reproduction of the vulnerable code pattern from registration.c L289-292
void freenect_init_registration_table_buggy() {
    // Simulate malloc failure
    double* regtable_dx = NULL;  // malloc fails
    double* regtable_dy = (double*)malloc(640 * 480 * sizeof(double));

    // Original code: no NULL check before memset
    memset(regtable_dx, 0, 640 * 480 * sizeof(double));  // CRASH
    memset(regtable_dy, 0, 640 * 480 * sizeof(double));

    free(regtable_dy);
}

int main() {
    __try {
        freenect_init_registration_table_buggy();
    }
    __except(1) {
        printf("ACCESS VIOLATION: NULL pointer dereference in memset confirmed\n");
    }
    return 0;
}

Result:

ACCESS VIOLATION: NULL pointer dereference in memset confirmed

How it was found

This bug was identified as PROP-N4-npd-005 during a SPECA security audit.

…tration_table

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
kebasaa added a commit to kebasaa/libfreenect that referenced this pull request Nov 9, 2026
…s checks

- The registration block (command 0x16, parameter 0x40) is read once in
  freenect_camera_init() for 640x480 at 30 fps, as Microsoft's init
  script does ([0x40, 0, 1, 30, 0], §20.1.1). It was read again at every
  freenect_set_video_mode() with that mode's resolution, which the 1414
  refuses for hi-res colour ("read 4 bytes (expected 118)"); the mapping
  for every colour resolution uses the 640x480 block (§20.5.2).
- Every table allocation is checked (the idea of upstream PR OpenKinect#698, for
  all of them): freenect_init_registration() returns -1 and
  freenect_start_depth() fails instead of writing through NULL;
  freenect_copy_registration() returns NULL tables when out of memory.
- freenect_map_rgb_to_depth() returns without doing anything when its
  arguments are NULL or the device has no registration tables (depth not
  started in a millimetre mode), skips 10000 mm (FREENECT_DEPTH_MM's
  saturation value, one past the end of the shift table) and drops
  colour rows outside the image instead of writing out of bounds.
- freenect_camera_to_world() and freenect_destroy_registration() accept
  NULL.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant