windowscodecs: Ignore the length field of RLE compressed bitmaps.

Vincent Povirk madewokherd at gmail.com
Fri Jul 16 13:45:33 CDT 2010


For bug 23214.
-------------- next part --------------
From eb64ce89c87853378fd8e23cfb13aea1884ad162 Mon Sep 17 00:00:00 2001
From: Vincent Povirk <vincent at codeweavers.com>
Date: Fri, 16 Jul 2010 12:31:49 -0500
Subject: [PATCH] windowscodecs: Ignore the length field of RLE compressed bitmaps.

---
 dlls/windowscodecs/bmpdecode.c |  171 +++++++++++++++++++++++++++-------------
 1 files changed, 115 insertions(+), 56 deletions(-)

diff --git a/dlls/windowscodecs/bmpdecode.c b/dlls/windowscodecs/bmpdecode.c
index 854b337..9cdc8e5 100644
--- a/dlls/windowscodecs/bmpdecode.c
+++ b/dlls/windowscodecs/bmpdecode.c
@@ -395,32 +395,52 @@ fail:
     return hr;
 }
 
+static HRESULT ReadByte(IStream *stream, BYTE *buffer, ULONG buffer_size,
+    ULONG *cursor, ULONG *bytesread, BYTE *result)
+{
+    HRESULT hr=S_OK;
+
+    if (*bytesread == 0 || *cursor == *bytesread)
+    {
+        hr = IStream_Read(stream, buffer, buffer_size, bytesread);
+        *cursor = 0;
+    }
+
+    if (SUCCEEDED(hr))
+    {
+        if (*cursor < *bytesread)
+            *result = buffer[(*cursor)++];
+        else
+            hr = E_FAIL;
+    }
+
+    return hr;
+}
+
 static HRESULT BmpFrameDecode_ReadRLE8(BmpDecoder* This)
 {
     UINT bytesperrow;
     UINT width, height;
-    BYTE *rledata, *cursor, *rledataend;
-    UINT rlesize, datasize, palettesize;
+    BYTE rledata[4096];
+    UINT datasize, palettesize;
     DWORD palette[256];
     UINT x, y;
     DWORD *bgrdata;
     HRESULT hr;
     LARGE_INTEGER offbits;
-    ULONG bytesread;
+    ULONG cursor=0, bytesread=0;
 
     width = This->bih.bV5Width;
     height = abs(This->bih.bV5Height);
     bytesperrow = width * 4;
     datasize = bytesperrow * height;
-    rlesize = This->bih.bV5SizeImage;
     if (This->bih.bV5ClrUsed && This->bih.bV5ClrUsed < 256)
         palettesize = 4 * This->bih.bV5ClrUsed;
     else
         palettesize = 4 * 256;
 
-    rledata = HeapAlloc(GetProcessHeap(), 0, rlesize);
     This->imagedata = HeapAlloc(GetProcessHeap(), 0, datasize);
-    if (!This->imagedata || !rledata)
+    if (!This->imagedata)
     {
         hr = E_OUTOFMEMORY;
         goto fail;
@@ -439,22 +459,26 @@ static HRESULT BmpFrameDecode_ReadRLE8(BmpDecoder* This)
     hr = IStream_Seek(This->stream, offbits, STREAM_SEEK_SET, NULL);
     if (FAILED(hr)) goto fail;
 
-    hr = IStream_Read(This->stream, rledata, rlesize, &bytesread);
-    if (FAILED(hr) || bytesread != rlesize) goto fail;
-
     /* decode RLE */
     bgrdata = (DWORD*)This->imagedata;
     x = 0;
     y = 0;
-    rledataend = rledata + rlesize;
-    cursor = rledata;
-    while (cursor < rledataend && y < height)
+    cursor = 0;
+    bytesread = 0;
+    while (y < height)
     {
-        BYTE length = *cursor++;
-        if (length == 0)
+        BYTE length;
+        hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &length);
+
+        if (FAILED(hr))
+            goto fail;
+        else if (length == 0)
         {
             /* escape code */
-            BYTE escape = *cursor++;
+            BYTE escape;
+            hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &escape);
+            if (FAILED(hr))
+                goto fail;
             switch(escape)
             {
             case 0: /* end of line */
@@ -464,37 +488,53 @@ static HRESULT BmpFrameDecode_ReadRLE8(BmpDecoder* This)
             case 1: /* end of bitmap */
                 goto end;
             case 2: /* delta */
-                if (cursor < rledataend)
-                {
-                    x += *cursor++;
-                    y += *cursor++;
-                }
+            {
+                BYTE dx, dy;
+                hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &dx);
+                if (SUCCEEDED(hr))
+                    hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &dy);
+                if (FAILED(hr))
+                    goto fail;
+                x += dx;
+                y += dy;
                 break;
+            }
             default: /* absolute mode */
                 length = escape;
-                while (cursor < rledataend && length-- && x < width)
-                    bgrdata[y*width + x++] = palette[*cursor++];
-                if (escape & 1) cursor++; /* skip pad byte */
+                while (length-- && x < width)
+                {
+                    BYTE index;
+                    hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &index);
+                    if (FAILED(hr))
+                        goto fail;
+                    bgrdata[y*width + x++] = palette[index];
+                }
+                if (escape & 1)
+                    hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &length); /* skip pad byte */
+                if (FAILED(hr))
+                    goto fail;
             }
         }
         else
         {
-            DWORD color = palette[*cursor++];
+            BYTE index;
+            DWORD color;
+            hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &index);
+            if (FAILED(hr))
+                goto fail;
+            color = palette[index];
             while (length-- && x < width)
                 bgrdata[y*width + x++] = color;
         }
     }
 
 end:
-    HeapFree(GetProcessHeap(), 0, rledata);
-
     This->imagedatastart = This->imagedata + (height-1) * bytesperrow;
     This->stride = -bytesperrow;
 
     return S_OK;
 
 fail:
-    HeapFree(GetProcessHeap(), 0, rledata);
     HeapFree(GetProcessHeap(), 0, This->imagedata);
     This->imagedata = NULL;
     if (SUCCEEDED(hr)) hr = E_FAIL;
@@ -505,28 +545,26 @@ static HRESULT BmpFrameDecode_ReadRLE4(BmpDecoder* This)
 {
     UINT bytesperrow;
     UINT width, height;
-    BYTE *rledata, *cursor, *rledataend;
-    UINT rlesize, datasize, palettesize;
+    BYTE rledata[4096];
+    UINT datasize, palettesize;
     DWORD palette[16];
     UINT x, y;
     DWORD *bgrdata;
     HRESULT hr;
     LARGE_INTEGER offbits;
-    ULONG bytesread;
+    ULONG cursor=0, bytesread=0;
 
     width = This->bih.bV5Width;
     height = abs(This->bih.bV5Height);
     bytesperrow = width * 4;
     datasize = bytesperrow * height;
-    rlesize = This->bih.bV5SizeImage;
     if (This->bih.bV5ClrUsed && This->bih.bV5ClrUsed < 16)
         palettesize = 4 * This->bih.bV5ClrUsed;
     else
         palettesize = 4 * 16;
 
-    rledata = HeapAlloc(GetProcessHeap(), 0, rlesize);
     This->imagedata = HeapAlloc(GetProcessHeap(), 0, datasize);
-    if (!This->imagedata || !rledata)
+    if (!This->imagedata)
     {
         hr = E_OUTOFMEMORY;
         goto fail;
@@ -545,22 +583,26 @@ static HRESULT BmpFrameDecode_ReadRLE4(BmpDecoder* This)
     hr = IStream_Seek(This->stream, offbits, STREAM_SEEK_SET, NULL);
     if (FAILED(hr)) goto fail;
 
-    hr = IStream_Read(This->stream, rledata, rlesize, &bytesread);
-    if (FAILED(hr) || bytesread != rlesize) goto fail;
-
     /* decode RLE */
     bgrdata = (DWORD*)This->imagedata;
     x = 0;
     y = 0;
-    rledataend = rledata + rlesize;
-    cursor = rledata;
-    while (cursor < rledataend && y < height)
+    cursor = 0;
+    bytesread = 0;
+    while (y < height)
     {
-        BYTE length = *cursor++;
-        if (length == 0)
+        BYTE length;
+        hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &length);
+
+        if (FAILED(hr))
+            goto fail;
+        else if (length == 0)
         {
             /* escape code */
-            BYTE escape = *cursor++;
+            BYTE escape;
+            hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &escape);
+            if (FAILED(hr))
+                goto fail;
             switch(escape)
             {
             case 0: /* end of line */
@@ -570,31 +612,51 @@ static HRESULT BmpFrameDecode_ReadRLE4(BmpDecoder* This)
             case 1: /* end of bitmap */
                 goto end;
             case 2: /* delta */
-                if (cursor < rledataend)
-                {
-                    x += *cursor++;
-                    y += *cursor++;
-                }
+            {
+                BYTE dx, dy;
+                hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &dx);
+                if (SUCCEEDED(hr))
+                    hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &dy);
+                if (FAILED(hr))
+                    goto fail;
+                x += dx;
+                y += dy;
                 break;
+            }
             default: /* absolute mode */
+            {
+                BYTE realsize=0;
                 length = escape;
-                while (cursor < rledataend && length-- && x < width)
+                while (length-- && x < width)
                 {
-                    BYTE colors = *cursor++;
+                    BYTE colors;
+                    hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &colors);
+                    realsize++;
+                    if (FAILED(hr))
+                        goto fail;
                     bgrdata[y*width + x++] = palette[colors>>4];
                     if (length-- && x < width)
                         bgrdata[y*width + x++] = palette[colors&0xf];
                     else
                         break;
                 }
-                if ((cursor - rledata) & 1) cursor++; /* skip pad byte */
+                if (realsize & 1)
+                    hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &length); /* skip pad byte */
+                if (FAILED(hr))
+                    goto fail;
+            }
             }
         }
         else
         {
-            BYTE colors = *cursor++;
-            DWORD color1 = palette[colors>>4];
-            DWORD color2 = palette[colors&0xf];
+            BYTE colors;
+            DWORD color1;
+            DWORD color2;
+            hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &colors);
+            if (FAILED(hr))
+                goto fail;
+            color1 = palette[colors>>4];
+            color2 = palette[colors&0xf];
             while (length-- && x < width)
             {
                 bgrdata[y*width + x++] = color1;
@@ -607,15 +669,12 @@ static HRESULT BmpFrameDecode_ReadRLE4(BmpDecoder* This)
     }
 
 end:
-    HeapFree(GetProcessHeap(), 0, rledata);
-
     This->imagedatastart = This->imagedata + (height-1) * bytesperrow;
     This->stride = -bytesperrow;
 
     return S_OK;
 
 fail:
-    HeapFree(GetProcessHeap(), 0, rledata);
     HeapFree(GetProcessHeap(), 0, This->imagedata);
     This->imagedata = NULL;
     if (SUCCEEDED(hr)) hr = E_FAIL;
-- 
1.7.0.4


More information about the wine-patches mailing list