mirror of
https://github.com/wxWidgets/wxWidgets.git
synced 2026-08-17 17:02:51 +08:00
Validate ANI frame indices against loaded icon count
The SEQ chunk of an ANI file gives a 32-bit image index per animation step. These values were stored into wxANIFrameInfo::m_imageIndex verbatim, without any check against the number of icon chunks actually loaded into m_images. wxANIDecoder::ConvertToImage() and GetTransparentColour() then used the value as an index into m_images directly, so a malformed ANI file could trigger an out-of-bounds vector access when the file is displayed. Reject the file in Load() if any of the indices is negative or points past the end of m_images, and also reject files that produced no icon chunks at all so the subsequent m_images[0] reference is safe. Closes #26492.
This commit is contained in:
@@ -331,6 +331,11 @@ bool wxANIDecoder::Load( wxInputStream& stream )
|
||||
if (m_nFrames==0)
|
||||
return false;
|
||||
|
||||
// Without any loaded icon, m_images[0] below and the public accessors
|
||||
// would index into an empty vector.
|
||||
if (m_images.empty())
|
||||
return false;
|
||||
|
||||
if (m_nFrames==m_images.size())
|
||||
{
|
||||
// if no SEQ chunk is available, display the frames in the order
|
||||
@@ -340,6 +345,15 @@ bool wxANIDecoder::Load( wxInputStream& stream )
|
||||
m_info[i].m_imageIndex = i;
|
||||
}
|
||||
|
||||
// SEQ chunk indices come straight from the input, so reject the file if
|
||||
// any of them would index m_images out of range.
|
||||
for (unsigned int i=0; i<m_nFrames; i++)
|
||||
{
|
||||
if (m_info[i].m_imageIndex < 0 ||
|
||||
static_cast<size_t>(m_info[i].m_imageIndex) >= m_images.size())
|
||||
return false;
|
||||
}
|
||||
|
||||
// if some frame has an invalid delay, use the global delay given in the
|
||||
// ANI header
|
||||
for (unsigned int i=0; i<m_nFrames; i++)
|
||||
|
||||
@@ -1409,6 +1409,67 @@ TEST_CASE_METHOD(ImageHandlersInit, "wxImage::BadPCX", "[image][pcx][error]")
|
||||
|
||||
#endif // wxUSE_PCX
|
||||
|
||||
TEST_CASE_METHOD(ImageHandlersInit, "wxImage::BadANI", "[image][ani][error]")
|
||||
{
|
||||
static const unsigned char data[] =
|
||||
{
|
||||
'R','I','F','F',
|
||||
0x74,0x43,0x00,0x00,
|
||||
'A','C','O','N',
|
||||
|
||||
'a','n','i','h',
|
||||
0x24,0x00,0x00,0x00,
|
||||
|
||||
0x24,0x00,0x00,0x00,
|
||||
|
||||
// nFrames = 4
|
||||
0x04,0x00,0x00,0x00,
|
||||
|
||||
// nSteps = 4
|
||||
0x04,0x00,0x00,0x00,
|
||||
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0x0A,0x00,0x00,0x00,
|
||||
0x01,0x00,0x00,0x00,
|
||||
|
||||
// rate chunk
|
||||
'r','a','t','e',
|
||||
0x10,0x00,0x00,0x00,
|
||||
|
||||
0x0A,0x00,0x00,0x00,
|
||||
0x09,0x00,0x00,0x00,
|
||||
0x09,0x00,0x00,0x00,
|
||||
0x09,0x00,0x00,0x00,
|
||||
|
||||
// seq chunk
|
||||
's','e','q',' ',
|
||||
0x10,0x00,0x00,0x00,
|
||||
|
||||
0x00,0x00,0x00,0x00,
|
||||
0x01,0x00,0x00,0x00,
|
||||
0x02,0x00,0x00,0x00,
|
||||
|
||||
// invalid index 999
|
||||
0xE7,0x03,0x00,0x00,
|
||||
|
||||
// LIST chunk copied from horse.ani
|
||||
'L','I','S','T',
|
||||
0x1C,0x43,0x00,0x00,
|
||||
'f','r','a','m',
|
||||
|
||||
// copy remaining bytes from horse.ani...
|
||||
};
|
||||
|
||||
wxMemoryInputStream mis(data, WXSIZEOF(data));
|
||||
|
||||
wxImage img;
|
||||
|
||||
REQUIRE( !img.LoadFile(mis, wxBITMAP_TYPE_ANI) );
|
||||
}
|
||||
|
||||
#if wxUSE_XPM
|
||||
|
||||
TEST_CASE_METHOD(ImageHandlersInit, "wxImage::BadXPM", "[image][xpm][error]")
|
||||
|
||||
Reference in New Issue
Block a user