diff --git a/src/common/imagtga.cpp b/src/common/imagtga.cpp index dec61a22f5..1a6f61e5d6 100644 --- a/src/common/imagtga.cpp +++ b/src/common/imagtga.cpp @@ -294,6 +294,18 @@ int ReadTGA(wxImage* image, wxInputStream& stream) // Load a palette if we have one. if (colorType == wxTGA_MAPPED) { + // The palette buffer below is sized for paletteLength entries + // indexed 0..paletteLength-1, and the wxPalette built from it + // later (see SetPalette() below) is constructed starting at + // index 0 as well. The loop writes entries at indices + // [paletteStart, paletteStart+paletteLength), so any non-zero + // paletteStart would cause Palette_SetRGB()/Palette_SetRGBA() + // to write past the end of the buffer. + if (paletteStart != 0) + { + return wxTGA_INVFORMAT; + } + { int palEntrySize = (palettebpp == 15 || palettebpp == 24) ? 3 : 4; wxScopedArray paletteTmp(paletteLength*palEntrySize); diff --git a/tests/image/image.cpp b/tests/image/image.cpp index fe4dbf051b..4917182b88 100644 --- a/tests/image/image.cpp +++ b/tests/image/image.cpp @@ -1187,6 +1187,48 @@ TEST_CASE_METHOD(ImageHandlersInit, "wxImage::ReadCorruptedTGA", "[image]") */ corruptTGA[18] = 0x7f; REQUIRE( !tgaImage.LoadFile(memIn) ); + + /* + A colour-mapped TGA with a non-zero colour-map origin. + Older code allocated the palette using paletteLength only, but + indexed it using paletteStart + i, leading to OOB writes. + */ + static const unsigned char badPaletteTGA[] = + { + 0, // ID length + 1, // Color map type + 1, // Image type = color mapped + + 1, 0, // Color map origin (paletteStart = 1) + 1, 0, // Color map length = 1 entry + 24, // Color map entry size + + 0, 0, // X-origin + 0, 0, // Y-origin + + 1, 0, // Width = 1 + 1, 0, // Height = 1 + + 8, // Bits per pixel + 0, // Image descriptor + + // One palette entry (BGR) + 0xff, 0x00, 0x00, + + // One pixel index + 0x00 + }; + + wxMemoryInputStream badPaletteStream( + badPaletteTGA, + WXSIZEOF(badPaletteTGA) + ); + + REQUIRE( badPaletteStream.IsOk() ); + + REQUIRE( + !tgaImage.LoadFile(badPaletteStream, wxBITMAP_TYPE_TGA) + ); } #if wxUSE_GIF