ReadTGA() sizes the image and the scratch buffer from the header without comparing them against the stream, then never checks how much the reads actually returned.
L447 reads into that buffer:
https://github.com/wxWidgets/wxWidgets/blob/d5aacc47127fb63a48fbf3a092ac0af1ecbd9200/src/common/imagtga.cpp#L447
and L489 decodes all of it:
https://github.com/wxWidgets/wxWidgets/blob/d5aacc47127fb63a48fbf3a092ac0af1ecbd9200/src/common/imagtga.cpp#L489
LastRead() and Eof() appear nowhere in the file, and ReadTGA() ends at :786 with return wxTGA_OK.
A 22 byte file declaring 31232x16382 at 24bpp allocates 1534927872 bytes for the image and 1534927872 more for the scratch buffer, then loads:
LoadFile=true, image is 31232x16382
With less memory available it aborts instead. Under ulimit -v 2097152, the wxImage::Create() allocation succeeds and the scratch one throws:
terminate called after throwing an instance of 'std::bad_alloc'
Aborted (core dumped)
The if (!imageData) check at :266 cannot catch that, since wxScopedArray uses new T[count], so wxTGA_MEMERR is never returned for this buffer.
The RLE paths already reject this. Two 22 byte files with identical headers apart from the image type byte:
RLE, 1000x1000, 4 bytes of data LoadFile=false
uncompressed, 1000x1000, 4 bytes of data LoadFile=true
DecodeRLE() validates its reads and bounds its output against imageSize, which is also what makes the existing wxImage::ReadCorruptedTGA test pass. The uncompressed paths do neither.
Expected: LoadFile() fails when the header declares more pixel data than the stream holds.
Observed: it allocates the declared size and returns true.
Not a crash.
#include "wx/init.h" #include "wx/mstream.h" #include "wx/image.h" #include "wx/imagtga.h" #include <cstdio> int main() { wxInitializer init; // 22 bytes: uncompressed RGB, 24bpp, 31232x16382 after origin subtraction. static const unsigned char tga[] = { 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00, 0x00,0x7a,0x00,0x40,0x18,0x20,0x00,0x00,0xff,0xff }; wxMemoryInputStream mis(tga, sizeof(tga)); wxImage img; wxTGAHandler h; const bool ok = h.LoadFile(&img, mis, false); if ( ok ) printf("LoadFile=true, image is %dx%d\n", img.GetWidth(), img.GetHeight()); else printf("LoadFile=false\n"); return 0; }
g++ repro.cpp -o repro $(wx-config --cxxflags --libs core,base)./repro prints LoadFile=true, image is 31232x16382, having allocated about 3 GB. Run it again under ulimit -v 2097152 and it aborts.Found by fuzzing the TGA handler. I have a patch with regression tests and can open a PR.
d5aacc4712. Reproduced on both. src/common/imagtga.cpp is byte-identical between them, and the same unguarded code is in 3.2.11 and in every earlier release back to 3.2.9—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.![]()
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.![]()