Skip to content

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

@iurisilvio

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions