[PATCH] gdiplus: Fix test crash in GdipSaveImageToStream.

Lei Zhang thestig at google.com
Fri Mar 14 11:30:38 CDT 2008


On Tue, Mar 11, 2008 at 10:26 PM, Nathan Beckmann
<nathan.beckmann at gmail.com> wrote:
> Correctly initialized parameters to GetDIBits. (Based on
>  GdipLockBitmapBits.)
>
>  Testing seems to indicate that the error doesn't occur on Debian, but
>  shows up in Slackware. Valgrind also complains.
>  ---
>   dlls/gdiplus/image.c |   28 ++++++++++++++++++++++------
>   1 files changed, 22 insertions(+), 6 deletions(-)
>
>  diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c
>  index 8307938..ad15148 100644
>  --- a/dlls/gdiplus/image.c
>  +++ b/dlls/gdiplus/image.c
>  @@ -908,7 +908,9 @@ GpStatus WINGDIPAPI GdipSaveImageToStream(GpImage *image, IStream* stream,
>      HRESULT hr;
>      short type;
>      HBITMAP hbmp;
>  +    HBITMAP old_hbmp;
>      HDC hdc;
>  +    int bm_is_selected;
>      BITMAPINFO bmp_info;
>      LPVOID bmp_bits;
>      encode_image_func* encode_image;
>  @@ -917,6 +919,7 @@ GpStatus WINGDIPAPI GdipSaveImageToStream(GpImage *image, IStream* stream,
>      unsigned int dummy;
>      int i;
>
>  +    old_hbmp = 0;
>      output = NULL;
>      output_size = 0;
>
>  @@ -943,18 +946,32 @@ GpStatus WINGDIPAPI GdipSaveImageToStream(GpImage *image, IStream* stream,
>      hr = IPicture_get_Handle(image->picture, (OLE_HANDLE*)&hbmp);
>      if (FAILED(hr) || !hbmp)
>          return GenericError;
>  +    hr = IPicture_get_CurDC(image->picture, &hdc);
>  +    if (FAILED(hr))
>  +        return GenericError;
>  +    bm_is_selected = (hdc != 0);
>  +    if (!bm_is_selected) {
>  +        hdc = CreateCompatibleDC(0);
>  +        old_hbmp = SelectObject(hdc, hbmp);
>  +    }
>
>      /* get bits from HBITMAP */
>  -    hdc = GetDC(0);
>      bmp_info.bmiHeader.biSize = sizeof(bmp_info.bmiHeader);
>  +    bmp_info.bmiHeader.biBitCount = 0;
>      GetDIBits(hdc, hbmp, 0, 0, NULL, &bmp_info, DIB_RGB_COLORS);
>
>      bmp_bits = GdipAlloc(bmp_info.bmiHeader.biSizeImage);
>  -    if (!bmp_bits) {
>  -        ReleaseDC(0, hdc);
>  -        return OutOfMemory;
>  +
>  +    if (bmp_bits)
>  +        GetDIBits(hdc, hbmp, 0, abs(bmp_info.bmiHeader.biHeight), bmp_bits, &bmp_info, DIB_RGB_COLORS);
>  +
>  +    if (!bm_is_selected) {
>  +        SelectObject(hdc, old_hbmp);
>  +        DeleteDC(hdc);
>      }
>  -    GetDIBits(hdc, hbmp, 0, bmp_info.bmiHeader.biHeight, bmp_bits, &bmp_info, DIB_RGB_COLORS);
>  +
>  +    if (!bmp_bits)
>  +        return OutOfMemory;
>
>      stat = encode_image(bmp_bits, &bmp_info, &output, &output_size);
>      if (stat == Ok)
>  @@ -962,7 +979,6 @@ GpStatus WINGDIPAPI GdipSaveImageToStream(GpImage *image, IStream* stream,
>
>      GdipFree(output);
>      GdipFree(bmp_bits);
>  -    ReleaseDC(0, hdc);
>
>      return stat;
>   }
>  --
>  1.5.4.2
>
>
>
>

FYI, here's the valgrind log:

http://www.kegel.com/wine/valgrind/logs-2008-03-11/vg-gdiplus_image-diff.txt

We're passing an uninitialized bmp_info into GetDIBits(), but somehow
it magically works on Debian.



More information about the wine-devel mailing list