[Git][wxwidgets/wxwidgets][master] 2 commits: Validate 4-bit BMP palette index against number of colors

3 views
Skip to first unread message

Vadim Zeitlin (@_VZ_)

unread,
May 26, 2026, 6:05:39 PM (11 days ago) May 26
to wx-commi...@googlegroups.com

Vadim Zeitlin pushed to branch master at wxWidgets / wxWidgets

Commits:

  • b47e2bb3
    by dxbjavid at 2026-05-26T23:51:04+02:00
    Validate 4-bit BMP palette index against number of colors
    
    Fix out-of-bounds read when decoding 4bpp BMP with invalid palette
    indices.
    
    Closes #26511.
    
  • 975dc5e5
    by Steve Cornett at 2026-05-26T23:58:34+02:00
    wxMSW: Repaint all windows upon system color change
    
    The problem is when the system switches between dark and light mode,
    Refresh() is never called. More specifically, when WM_SETTINGCHANGE
    occurs with "ImmersiveColorSet", HandleSettingChange() is not called.
    But that is where the only Refresh() call is.
    
    Top level windows should get Refresh() upon WM_SYSCOLORCHANGE as well as
    WM_SETTINGCHANGE. Adding another Refresh() call into
    HandleSysColorChange() solves the problem.
    
    Closes #26514.
    

3 changed files:

Changes:

  • src/common/imagbmp.cpp
    ... ... @@ -783,6 +783,8 @@ bool LoadBMPData(wxImage * image, const BMPDesc& desc,
    783 783
                                             nibble[0] = (wxUint8)( (aByte & 0xF0) >> 4 ) ;
    
    784 784
                                             nibble[1] = (wxUint8)( aByte & 0x0F ) ;
    
    785 785
                                         }
    
    786
    +                                    if ( nibble[k%2] >= ncolors )
    
    787
    +                                        return false;
    
    786 788
                                         ptr[poffset    ] = cmap[nibble[k%2]].r;
    
    787 789
                                         ptr[poffset + 1] = cmap[nibble[k%2]].g;
    
    788 790
                                         ptr[poffset + 2] = cmap[nibble[k%2]].b;
    
    ... ... @@ -804,6 +806,8 @@ bool LoadBMPData(wxImage * image, const BMPDesc& desc,
    804 806
     
    
    805 807
                                 for ( int l = 0; l < first && column < width; l++ )
    
    806 808
                                 {
    
    809
    +                                if ( nibble[l%2] >= ncolors )
    
    810
    +                                    return false;
    
    807 811
                                     ptr[poffset    ] = cmap[nibble[l%2]].r;
    
    808 812
                                     ptr[poffset + 1] = cmap[nibble[l%2]].g;
    
    809 813
                                     ptr[poffset + 2] = cmap[nibble[l%2]].b;
    
    ... ... @@ -816,8 +820,8 @@ bool LoadBMPData(wxImage * image, const BMPDesc& desc,
    816 820
                             for (int nibble = 0; nibble < 2 && column < width; nibble++)
    
    817 821
                             {
    
    818 822
                                 int index = ((aByte & (0xF0 >> (nibble * 4))) >> (!nibble * 4));
    
    819
    -                            if ( index >= 16 )
    
    820
    -                                index = 15;
    
    823
    +                            if ( index >= ncolors )
    
    824
    +                                return false;
    
    821 825
                                 ptr[poffset] = cmap[index].r;
    
    822 826
                                 ptr[poffset + 1] = cmap[index].g;
    
    823 827
                                 ptr[poffset + 2] = cmap[index].b;
    

  • src/msw/window.cpp
    ... ... @@ -5110,6 +5110,9 @@ bool wxWindowMSW::HandleSysColorChange()
    5110 5110
     
    
    5111 5111
         (void)HandleWindowEvent(event);
    
    5112 5112
     
    
    5113
    +    if ( IsTopLevel() )
    
    5114
    +        Refresh();
    
    5115
    +
    
    5113 5116
         // always let the system carry on the default processing to allow the
    
    5114 5117
         // native controls to react to the colours update
    
    5115 5118
         return false;
    

  • tests/image/image.cpp
    ... ... @@ -1231,6 +1231,41 @@ TEST_CASE_METHOD(ImageHandlersInit, "wxImage::ReadCorruptedTGA", "[image]")
    1231 1231
         );
    
    1232 1232
     }
    
    1233 1233
     
    
    1234
    +TEST_CASE_METHOD(ImageHandlersInit, "wxImage::BadBMPPaletteIndex", "[image][bmp][error]")
    
    1235
    +{
    
    1236
    +    // A 4-bit BMP that declares only a single palette entry (biClrUsed = 1)
    
    1237
    +    // but uses a higher nibble value as the pixel index. The 8-bit decode
    
    1238
    +    // path rejects indices >= ncolors, but the 4-bit path used to read
    
    1239
    +    // cmap[index] for any 0..15 nibble, running past the palette array.
    
    1240
    +    static const unsigned char data[] =
    
    1241
    +    {
    
    1242
    +        'B','M',
    
    1243
    +        0x3e,0,0,0,         // file size = 62
    
    1244
    +        0,0,0,0,            // reserved
    
    1245
    +        0x3a,0,0,0,         // pixel data offset = 58
    
    1246
    +
    
    1247
    +        0x28,0,0,0,         // DIB header size = 40
    
    1248
    +        1,0,0,0,            // width = 1
    
    1249
    +        1,0,0,0,            // height = 1
    
    1250
    +        1,0,                // planes
    
    1251
    +        4,0,                // bpp = 4
    
    1252
    +        0,0,0,0,            // compression = BI_RGB
    
    1253
    +        0,0,0,0,            // image size
    
    1254
    +        0,0,0,0,            // x ppm
    
    1255
    +        0,0,0,0,            // y ppm
    
    1256
    +        1,0,0,0,            // biClrUsed = 1
    
    1257
    +        0,0,0,0,            // biClrImportant
    
    1258
    +
    
    1259
    +        0,0,0,0,            // single palette entry (BGRA)
    
    1260
    +
    
    1261
    +        0xf0,0,0,0          // one scanline, high nibble = 15
    
    1262
    +    };
    
    1263
    +
    
    1264
    +    wxMemoryInputStream mis(data, WXSIZEOF(data));
    
    1265
    +    wxImage img;
    
    1266
    +    REQUIRE( !img.LoadFile(mis, wxBITMAP_TYPE_BMP) );
    
    1267
    +}
    
    1268
    +
    
    1234 1269
     #if wxUSE_GIF
    
    1235 1270
     
    
    1236 1271
     TEST_CASE_METHOD(ImageHandlersInit, "wxImage::SaveAnimatedGIF", "[image]")
    

Reply all
Reply to author
Forward
0 new messages