Huw Davies : ole32: Don't cache the BITMAPFILEHEADER.

Alexandre Julliard julliard at winehq.org
Thu May 18 15:27:50 CDT 2017


Module: wine
Branch: master
Commit: e7bb4ba2697d5dfdf29387ac01f5f9f89487a38a
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=e7bb4ba2697d5dfdf29387ac01f5f9f89487a38a

Author: Huw Davies <huw at codeweavers.com>
Date:   Thu May 18 11:07:06 2017 +0100

ole32: Don't cache the BITMAPFILEHEADER.

Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ole32/datacache.c | 88 ++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 74 insertions(+), 14 deletions(-)

diff --git a/dlls/ole32/datacache.c b/dlls/ole32/datacache.c
index 0d3c2a9..0db5551 100644
--- a/dlls/ole32/datacache.c
+++ b/dlls/ole32/datacache.c
@@ -224,6 +224,35 @@ const char *debugstr_formatetc(const FORMATETC *formatetc)
         formatetc->lindex, formatetc->tymed);
 }
 
+/***********************************************************************
+ *           bitmap_info_size
+ *
+ * Return the size of the bitmap info structure including color table.
+ */
+int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
+{
+    unsigned int colors, size, masks = 0;
+
+    if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
+    {
+        const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
+        colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
+        return sizeof(BITMAPCOREHEADER) + colors *
+            ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
+    }
+    else  /* assume BITMAPINFOHEADER */
+    {
+        colors = info->bmiHeader.biClrUsed;
+        if (colors > 256) /* buffer overflow otherwise */
+            colors = 256;
+        if (!colors && (info->bmiHeader.biBitCount <= 8))
+            colors = 1 << info->bmiHeader.biBitCount;
+        if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
+        size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
+        return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
+    }
+}
+
 static void DataCacheEntry_Destroy(DataCache *cache, DataCacheEntry *cache_entry)
 {
     list_remove(&cache_entry->entry);
@@ -604,7 +633,8 @@ static HRESULT load_dib( DataCacheEntry *cache_entry, IStream *stm )
     STATSTG stat;
     void *dib;
     HGLOBAL hglobal;
-    ULONG read;
+    ULONG read, info_size, bi_size;
+    BITMAPFILEHEADER file;
 
     if (cache_entry->stream_type != contents_stream)
     {
@@ -615,24 +645,59 @@ static HRESULT load_dib( DataCacheEntry *cache_entry, IStream *stm )
     hr = IStream_Stat( stm, &stat, STATFLAG_NONAME );
     if (FAILED( hr )) return hr;
 
+    if (stat.cbSize.QuadPart < sizeof(file) + sizeof(DWORD)) return E_FAIL;
+    hr = IStream_Read( stm, &file, sizeof(file), &read );
+    if (hr != S_OK || read != sizeof(file)) return E_FAIL;
+    stat.cbSize.QuadPart -= sizeof(file);
+
     hglobal = GlobalAlloc( GMEM_MOVEABLE, stat.cbSize.u.LowPart );
     if (!hglobal) return E_OUTOFMEMORY;
     dib = GlobalLock( hglobal );
 
-    hr = IStream_Read( stm, dib, stat.cbSize.u.LowPart, &read );
-    GlobalUnlock( hglobal );
+    hr = IStream_Read( stm, dib, sizeof(DWORD), &read );
+    if (hr != S_OK || read != sizeof(DWORD)) goto fail;
+    bi_size = *(DWORD *)dib;
+    if (stat.cbSize.QuadPart < bi_size) goto fail;
+
+    hr = IStream_Read( stm, (char *)dib + sizeof(DWORD), bi_size - sizeof(DWORD), &read );
+    if (hr != S_OK || read != bi_size - sizeof(DWORD)) goto fail;
 
-    if (hr != S_OK || read != stat.cbSize.u.LowPart)
+    info_size = bitmap_info_size( dib, DIB_RGB_COLORS );
+    if (stat.cbSize.QuadPart < info_size) goto fail;
+    if (info_size > bi_size)
     {
-        GlobalFree( hglobal );
-        return E_FAIL;
+        hr = IStream_Read( stm, (char *)dib + bi_size, info_size - bi_size, &read );
+        if (hr != S_OK || read != info_size - bi_size) goto fail;
     }
+    stat.cbSize.QuadPart -= info_size;
+
+    if (file.bfOffBits)
+    {
+        LARGE_INTEGER skip;
+
+        skip.QuadPart = file.bfOffBits - sizeof(file) - info_size;
+        if (stat.cbSize.QuadPart < skip.QuadPart) goto fail;
+        hr = IStream_Seek( stm, skip, STREAM_SEEK_CUR, NULL );
+        if (hr != S_OK) goto fail;
+        stat.cbSize.QuadPart -= skip.QuadPart;
+    }
+
+    hr = IStream_Read( stm, (char *)dib + info_size, stat.cbSize.u.LowPart, &read );
+    if (hr != S_OK || read != stat.cbSize.QuadPart) goto fail;
+
+    GlobalUnlock( hglobal );
 
     cache_entry->data_cf = cache_entry->fmtetc.cfFormat;
     cache_entry->stgmedium.tymed = TYMED_HGLOBAL;
     cache_entry->stgmedium.u.hGlobal = hglobal;
 
     return S_OK;
+
+fail:
+    GlobalUnlock( hglobal );
+    GlobalFree( hglobal );
+    return E_FAIL;
+
 }
 
 /************************************************************************
@@ -1672,16 +1737,14 @@ static HRESULT WINAPI DataCache_Draw(
       }
       case CF_DIB:
       {
-          BITMAPFILEHEADER *file_head;
           BITMAPINFO *info;
           BYTE *bits;
 
           if ((cache_entry->stgmedium.tymed != TYMED_HGLOBAL) ||
-              !((file_head = GlobalLock( cache_entry->stgmedium.u.hGlobal ))))
+              !((info = GlobalLock( cache_entry->stgmedium.u.hGlobal ))))
               continue;
 
-          info = (BITMAPINFO *)(file_head + 1);
-          bits = (BYTE *) file_head + file_head->bfOffBits;
+          bits = (BYTE *) info + bitmap_info_size( info, DIB_RGB_COLORS );
           StretchDIBits( hdcDraw, lprcBounds->left, lprcBounds->top,
                          lprcBounds->right - lprcBounds->left, lprcBounds->bottom - lprcBounds->top,
                          0, 0, info->bmiHeader.biWidth, info->bmiHeader.biHeight,
@@ -1892,17 +1955,14 @@ static HRESULT WINAPI DataCache_GetExtent(
       }
       case CF_DIB:
       {
-          BITMAPFILEHEADER *file_head;
           BITMAPINFOHEADER *info;
           LONG x_pels_m, y_pels_m;
 
 
           if ((cache_entry->stgmedium.tymed != TYMED_HGLOBAL) ||
-              !((file_head = GlobalLock( cache_entry->stgmedium.u.hGlobal ))))
+              !((info = GlobalLock( cache_entry->stgmedium.u.hGlobal ))))
               continue;
 
-          info = (BITMAPINFOHEADER *)(file_head + 1);
-
           x_pels_m = info->biXPelsPerMeter;
           y_pels_m = info->biYPelsPerMeter;
 




More information about the wine-cvs mailing list