Avoid out-of-bounds palette read in 8bpp BMP decoder

The non-RLE 8bpp branch at imagbmp.cpp:903, plus the RLE absolute and
RLE encoded branches a few lines above, all index cmap[aByte] without
checking aByte against the palette colour count. A BMP that pairs a
small palette with a colour-index byte >= ncolors reads past the
palette and the value flows into the decoded pixel.

Reject the file (return false) at each site, matching the surrounding
"return false on malformed input" pattern.

Closes #26438.

Closes #26439.
This commit is contained in:
MarkLee131
2026-05-11 00:29:40 +02:00
committed by Vadim Zeitlin
parent 0b380e6f4f
commit b305cb4e4d
2 changed files with 26 additions and 0 deletions
+6
View File
@@ -873,6 +873,8 @@ bool LoadBMPData(wxImage * image, const BMPDesc& desc,
aByte = stream.GetC();
if ( !stream.IsOk() )
return false;
if ( aByte >= ncolors )
return false;
ptr[poffset ] = cmap[aByte].r;
ptr[poffset + 1] = cmap[aByte].g;
ptr[poffset + 2] = cmap[aByte].b;
@@ -889,6 +891,8 @@ bool LoadBMPData(wxImage * image, const BMPDesc& desc,
else
{
// encoded mode (repeat aByte first times)
if ( aByte >= ncolors )
return false;
for ( int l = 0; l < first && column < width; l++ )
{
ptr[poffset ] = cmap[aByte].r;
@@ -900,6 +904,8 @@ bool LoadBMPData(wxImage * image, const BMPDesc& desc,
}
else
{
if ( aByte >= ncolors )
return false;
ptr[poffset ] = cmap[aByte].r;
ptr[poffset + 1] = cmap[aByte].g;
ptr[poffset + 2] = cmap[aByte].b;
+20
View File
@@ -1678,6 +1678,26 @@ TEST_CASE_METHOD(ImageHandlersInit, "wxImage::BMP", "[image][bmp]")
LoadMalformedImage("image/badrle4.bmp", wxBITMAP_TYPE_BMP);
LoadMalformedImage("image/width-times-height-overflow.bmp", wxBITMAP_TYPE_BMP);
}
SECTION("8bpp colour index past end of palette")
{
// An 8bpp BMP whose pixel stream contains a colour index larger
// than the palette colour count. Used to read past the palette
// buffer in the decode loops.
static const unsigned char data[] =
{
0x42,0x4d,0x3a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x00,
0x00,0x00,0x28,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x01,0x00,
0x00,0x00,0x01,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x42,0x4d,0x3a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2b,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,
0x00,0x00,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x01,0x00,0x00,
};
wxMemoryInputStream mis(data, WXSIZEOF(data));
wxImage img;
REQUIRE( !img.LoadFile(mis, wxBITMAP_TYPE_BMP) );
}
wxImage image;
SECTION("32bpp alpha")
{