[PATCH] gdi32: Fix out-of-bounds reads in bitmapinfo_from_user_bitmapinfo (Valgrind)

Alex Henrie alexhenrie24 at gmail.com
Sun Oct 13 22:44:54 CDT 2019


Do not attempt to copy the bitmap colormap if there is no bitmap
colormap. Substitute the default colormap if possible.

Signed-off-by: Alex Henrie <alexhenrie24 at gmail.com>
---
 dlls/gdi32/dib.c | 39 ++++++++++++++++++++++-----------------
 1 file changed, 22 insertions(+), 17 deletions(-)

diff --git a/dlls/gdi32/dib.c b/dlls/gdi32/dib.c
index 3d267ba89c..7e9c21d3f5 100644
--- a/dlls/gdi32/dib.c
+++ b/dlls/gdi32/dib.c
@@ -204,14 +204,10 @@ static BOOL bitmapinfoheader_from_user_bitmapinfo( BITMAPINFOHEADER *dst, const
 static BOOL bitmapinfo_from_user_bitmapinfo( BITMAPINFO *dst, const BITMAPINFO *info,
                                              UINT coloruse, BOOL allow_compression )
 {
-    void *src_colors;
-
     if (coloruse > DIB_PAL_COLORS + 1) return FALSE;  /* FIXME: handle DIB_PAL_COLORS+1 format */
     if (!bitmapinfoheader_from_user_bitmapinfo( &dst->bmiHeader, &info->bmiHeader )) return FALSE;
     if (!is_valid_dib_format( &dst->bmiHeader, allow_compression )) return FALSE;
 
-    src_colors = (char *)info + info->bmiHeader.biSize;
-
     if (dst->bmiHeader.biCompression == BI_BITFIELDS)
     {
         /* bitfields are always at bmiColors even in larger structures */
@@ -220,31 +216,40 @@ static BOOL bitmapinfo_from_user_bitmapinfo( BITMAPINFO *dst, const BITMAPINFO *
     }
     else if (dst->bmiHeader.biBitCount <= 8)
     {
+        const void *src_colors = (char *)info + info->bmiHeader.biSize;
         unsigned int colors = dst->bmiHeader.biClrUsed;
         unsigned int max_colors = 1 << dst->bmiHeader.biBitCount;
 
-        if (!colors) colors = max_colors;
-        else colors = min( colors, max_colors );
+        colors = min( colors, max_colors );
 
         if (coloruse == DIB_PAL_COLORS)
         {
             memcpy( dst->bmiColors, src_colors, colors * sizeof(WORD) );
             max_colors = colors;
         }
-        else if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
-        {
-            memcpy( dst->bmiColors, src_colors, colors * sizeof(RGBQUAD) );
-        }
         else
         {
-            unsigned int i;
-            RGBTRIPLE *triple = (RGBTRIPLE *)src_colors;
-            for (i = 0; i < colors; i++)
+            if (!colors)
             {
-                dst->bmiColors[i].rgbRed      = triple[i].rgbtRed;
-                dst->bmiColors[i].rgbGreen    = triple[i].rgbtGreen;
-                dst->bmiColors[i].rgbBlue     = triple[i].rgbtBlue;
-                dst->bmiColors[i].rgbReserved = 0;
+                src_colors = get_default_color_table( dst->bmiHeader.biBitCount );
+                colors = max_colors;
+            }
+
+            if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
+            {
+                memcpy( dst->bmiColors, src_colors, colors * sizeof(RGBQUAD) );
+            }
+            else
+            {
+                unsigned int i;
+                RGBTRIPLE *triple = (RGBTRIPLE *)src_colors;
+                for (i = 0; i < colors; i++)
+                {
+                    dst->bmiColors[i].rgbRed      = triple[i].rgbtRed;
+                    dst->bmiColors[i].rgbGreen    = triple[i].rgbtGreen;
+                    dst->bmiColors[i].rgbBlue     = triple[i].rgbtBlue;
+                    dst->bmiColors[i].rgbReserved = 0;
+                }
             }
         }
         memset( dst->bmiColors + colors, 0, (max_colors - colors) * sizeof(RGBQUAD) );
-- 
2.23.0




More information about the wine-devel mailing list