Avoid out-of-bounds line-buffer read in wxPCXHandler::LoadFile (Issue #26441)

9 views
Skip to first unread message

MarkLee131

unread,
May 10, 2026, 6:03:10 PMMay 10
to wx-...@googlegroups.com, Subscribed
MarkLee131 created an issue (wxWidgets/wxWidgets#26441)

Description

Bug description:

ReadPCX allocates a per-line buffer p of size bytesperline * nplanes from the PCX header, then iterates for (i = 0; i < width; i++) *dst = p[i];. The header's width and bytesperline are independent fields and never cross-validated.

src/common/imagpcx.cpp:218 (allocation):

p = (unsigned char *) malloc(bytesperline * nplanes);

src/common/imagpcx.cpp:240 (8-bit decode loop):

for (i = 0; i < width; i++)
{
    *dst = p[i];                      // line 240, OOB when width > bytesperline*nplanes
    dst += 3;
}

The 24-bit branch a few lines below reads p[i], p[i + bytesperline], and p[i + 2*bytesperline], so the same condition gives up to 2*bytesperline + width worth of OOB read. A header with width >> bytesperline*nplanes produces a tiny allocation and walks width bytes into adjacent heap.

Found by an ASAN libFuzzer harness against wxPCXHandler::LoadFile.

Expected vs observed behaviour:

A PCX whose width exceeds bytesperline * nplanes should be rejected as malformed. Currently it reads heap memory adjacent to the per-line buffer and writes those bytes into the decoded image.

Stack trace:

==1==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7beef4622371
READ of size 1 at 0x7beef4622371 thread T0
    #0 ReadPCX  src/common/imagpcx.cpp:240:28
    #1 wxPCXHandler::LoadFile(wxImage*, wxInputStream&, bool, int)  src/common/imagpcx.cpp:447:18
    #2 LLVMFuzzerTestOneInput  tests/fuzz/pcx.cpp:13:7
0x7beef4622371 is located 0 bytes after 1-byte region [0x7beef4622370,0x7beef4622371)
allocated by:
    #0 malloc
    #1 ReadPCX  src/common/imagpcx.cpp:218:32
SUMMARY: AddressSanitizer: heap-buffer-overflow src/common/imagpcx.cpp:240:28 in ReadPCX

Patch or snippet allowing to reproduce the problem:

Drop the following as tests/fuzz/pcx.cpp next to the existing tests/fuzz/runner.cpp:

#include "wx/log.h"
#include "wx/mstream.h"
#include "wx/imagpcx.h"

extern "C" int LLVMFuzzerTestOneInput(const wxUint8* data, size_t size)
{
    wxLogNull noLog;
    wxMemoryInputStream mis(data, size);
    wxImage img;
    wxPCXHandler h;
    h.LoadFile(&img, mis, false);
    return 0;
}

128-byte PoC, hex below. Reconstruct with xxd -r -p hex.txt poc.pcx:

0a0501080000000008000000480048000000000000f300000000000000000000
0000000000000000000000000000000000000000000000000000000000000102
000100000a970000000000000000000000000000000000000000000000000000
000000000000000000000000000000000a970000000400000000000000c10000

Header sets bytesperline=0, nplanes=1, bitsperpixel=8, width=9. The product bytesperline*nplanes = 0, so malloc returns a zero-byte allocation (ASAN tracks this as a 1-byte region), and the decode loop walks 9 bytes off the end.

To Reproduce:

  1. Check out master at the current HEAD and apply the harness above to tests/fuzz/pcx.cpp.

  2. Save the hex above to a file and decode: xxd -r -p hex.txt poc.pcx.

  3. Build:

    clang++ -g -fsanitize=address tests/fuzz/{pcx,runner}.cpp \
        `wx-config --cxxflags --libs core,base` -o repro_pcx
    
  4. Run ./repro_pcx poc.pcx and observe the ASAN trace.

Suggested fix

Validate width > 0 && height > 0 && bytesperline > 0 && width <= bytesperline right after reading the header; reject otherwise (return wxPCX_INVFORMAT). Patch ready with an inline-bytes Catch2 regression test. Happy to send a PR.

Platform and version information

  • wxWidgets version: master at HEAD f57b17ba5f63db53dd1b465646ade105fee22302. Line 240 is unchanged at tag v3.3.2, and the same pattern is present at v3.2.0.
  • wxWidgets port: wxGTK.
  • OS: Ubuntu 22.04 (gcr.io/oss-fuzz-base/base-builder).


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/26441@github.com>

VZ

unread,
May 10, 2026, 7:29:48 PMMay 10
to wx-...@googlegroups.com, Subscribed

Closed #26441 as completed via edae38f.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issue/26441/issue_event/25360562643@github.com>

Reply all
Reply to author
Forward
0 new messages