Skip to content

Fix memory leak when reusing DmtxEncode across multiple encode calls#64

Open
94xhn wants to merge 1 commit into
dmtx:masterfrom
94xhn:fix/encode-reuse-leak
Open

Fix memory leak when reusing DmtxEncode across multiple encode calls#64
94xhn wants to merge 1 commit into
dmtx:masterfrom
94xhn:fix/encode-reuse-leak

Conversation

@94xhn

@94xhn 94xhn commented Jul 15, 2026

Copy link
Copy Markdown

Problem

dmtxEncodeDataMatrix() unconditionally does:

enc->message = dmtxMessageCreate(sizeIdx, DmtxFormatMatrix);
...
enc->image = dmtxImageCreate(pxl, width, height, enc->pixelPacking);

without freeing whatever enc->message / enc->image already held from a
previous call on the same DmtxEncode. Reusing one DmtxEncode across
multiple dmtxEncodeDataMatrix() calls (as shown in the repro below) leaks
the prior message and image on every call after the first.

Repro (see #40):

DmtxEncode *enc = dmtxEncodeCreate();
dmtxEncodeDataMatrix(enc, len1, data1);
dmtxEncodeDataMatrix(enc, len2, data2); /* leaks the first message+image */
dmtxEncodeDestroy(&enc);

Fix

Free the existing enc->message / enc->image (mirroring the logic
already used in dmtxEncodeDestroy(), including the pixel-buffer free)
immediately before allocating their replacements. Both fields are NULL
on a freshly created DmtxEncode, and dmtxMessageDestroy() /
dmtxImageDestroy() are already NULL-safe, so this is a no-op on the
first call — no behavior change for the common single-use case.

Testing

  • Built the amalgamated dmtx.c with GNU ld --wrap=malloc/calloc/free/realloc
    to count net (unfreed) allocations.
    • Before the fix: encoding twice then destroying once on the same
      DmtxEncode leaks ~6 allocations / ~30KB versus a single encode+destroy
      baseline (isolating library-internal allocations from libc/CRT
      startup noise, which is identical in both cases).
    • After the fix: the reuse case matches the single-call baseline exactly
      (no residual leak), including under a 5-cycle reuse stress test.
  • Round-trip correctness: reused one DmtxEncode to encode two different
    strings, decoded each resulting image independently, and confirmed both
    decode back to their original input — the added early frees don't
    corrupt or clobber the freshly created structures still in use.

Fixes #40

dmtxEncodeDataMatrix() unconditionally overwrote enc->message and
enc->image on every call without freeing any previous values held by
the same DmtxEncode struct. Reusing one DmtxEncode for multiple
dmtxEncodeDataMatrix() calls (a supported and documented pattern)
therefore leaked the prior message/image on each call.

Free the existing enc->message and enc->image (mirroring the logic
already used in dmtxEncodeDestroy()) immediately before allocating
their replacements. This is a no-op on the first call, since both
fields are NULL on a freshly created DmtxEncode.

Fixes dmtx#40
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.

Potential memory leak if DmtxEncode is re-used

1 participant