Skip to content

Allocator mismatch in decodeJPEGIntoSurface OOM path: free() called on new[]-allocated buffer #2573

Description

@iurisilvio

Bug

Image::decodeJPEGIntoSurface allocates a buffer with new uint8_t[] and frees it with free() on the OOM error path (src/Image.cc#L844). This is undefined behavior in C++ — new[] and free() may use different allocators and even when they share one they may have different bookkeeping (size header offset, etc.).

The triggering condition (the second new uint8_t[] returning nullptr after the first succeeds) is unlikely in practice, but the bug is real and g++ -Wmismatched-new-delete flags it on every build.

Diff

   uint8_t *data = new uint8_t[naturalWidth * naturalHeight * channels];
   if (!data) {
     jpeg_abort_decompress(args);
     jpeg_destroy_decompress(args);
     this->errorInfo.set(NULL, "malloc", errno);
     return CAIRO_STATUS_NO_MEMORY;
   }

   uint8_t *src = new uint8_t[naturalWidth * args->output_components];
   if (!src) {
-    free(data);
+    delete[] data;
     jpeg_abort_decompress(args);
     jpeg_destroy_decompress(args);
     this->errorInfo.set(NULL, "malloc", errno);
     return CAIRO_STATUS_NO_MEMORY;
   }

Every other deallocation of buffers from new uint8_t[] in Image.cc already uses delete[] (see lines 710, 898, 901, 991) — this is the only outlier.

Compiler warning

Building with node-gyp rebuild on g++ produces:

../src/Image.cc:844:9: warning: 'void free(void*)' called on pointer returned from a mismatched allocation function [-Wmismatched-new-delete]
  844 |     free(data);
      |     ~~~~^~~~~~
../src/Image.cc:834:70: note: returned from 'void* operator new []'(std::size_t)'
  834 |   uint8_t *data = new uint8_t[naturalWidth * naturalHeight * channels];
      |                                                                      ^

Fix

One-character change in the OOM error path: freedelete[]. PR to follow.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions