diff --git a/dlls/gdi32/dib.c b/dlls/gdi32/dib.c index d53b8f2..57d074c 100644 --- a/dlls/gdi32/dib.c +++ b/dlls/gdi32/dib.c @@ -193,6 +193,10 @@ INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, if (!bits || !info) return 0; + /* detect broken MFC apps which pass invalid bits pointer */ + if (IsBadReadPtr(bits, 1)) + return 0; + if (!(dc = get_dc_ptr( hdc ))) return FALSE; if(dc->funcs->pStretchDIBits) @@ -381,6 +385,10 @@ INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx, if (!bits) return 0; + /* detect broken MFC apps which pass invalid bits pointer */ + if (IsBadReadPtr(bits, 1)) + return 0; + if (!(dc = get_dc_ptr( hdc ))) return 0; if(dc->funcs->pSetDIBitsToDevice) diff --git a/dlls/gdi32/tests/bitmap.c b/dlls/gdi32/tests/bitmap.c index c31d367..7136866 100644 --- a/dlls/gdi32/tests/bitmap.c +++ b/dlls/gdi32/tests/bitmap.c @@ -1147,10 +1147,12 @@ static void test_GetDIBits_selected_DIB(UINT bpp) ok(equalContents, "GetDIBits with DIB selected in DC: Invalid DIB color table\n"); equalContents = TRUE; + trace("checking %d bytes\n", dib_size); for (i=0; i < dib_size / sizeof(DWORD); i++) { if (((DWORD *)bits)[i] != ((DWORD *)bits2)[i]) { + trace("bits[%d] %x != bits2[%d] %x \n", i, ((DWORD *)bits)[i], i, ((DWORD *)bits2)[i]); equalContents = FALSE; break; } @@ -2017,6 +2019,60 @@ void test_GdiAlphaBlend() } +static void test_badbits() +{ + char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)]; + BITMAPINFO *pbmi = (BITMAPINFO *)bmibuf; + HDC hdc0, hdc; + int ret; + void *bits; + DWORD oldprotect; + SYSTEM_INFO si; + + memset(pbmi, 0, sizeof(bmibuf)); + pbmi->bmiHeader.biSize = sizeof(pbmi->bmiHeader); + pbmi->bmiHeader.biHeight = 100; + pbmi->bmiHeader.biWidth = 100; + pbmi->bmiHeader.biBitCount = 24; + pbmi->bmiHeader.biPlanes = 1; + pbmi->bmiHeader.biCompression = BI_RGB; + hdc0 = GetDC(0); + hdc = CreateCompatibleDC( hdc0); + + GetSystemInfo( &si); + bits = VirtualAlloc( NULL, 40000, MEM_COMMIT, PAGE_READONLY); + ok( (int)bits, "VirtualAlloc failed\n"); + + /* source bits can be read, StretchDIBits succeeds */ + ret = StretchDIBits( hdc, 0, 0, 100, 100, 0, 0, 100, 100, bits, + pbmi, 0, SRCCOPY); + ok( ret, "StretchDIBits failed\n"); + + ret = VirtualProtect( (char*)bits, si.dwPageSize, + PAGE_NOACCESS, &oldprotect); + ok( ret, "VirtualProtect failed\n"); + /* source bits cannot all be read, StretchDIBits fails */ + /* and should not crash */ + ret = StretchDIBits( hdc, 0, 0, 100, 100, 0, 0, 100, 100, bits, + pbmi, 0, SRCCOPY); + ok( !ret, "StretchDIBits should have failed\n"); + + /* same tests for SetDIBitsToDevice */ + ret = SetDIBitsToDevice( hdc, 0, 0, 100, 100, 0, 0, 0, 100, bits, + pbmi, DIB_RGB_COLORS); + ok( !ret, "SetDIBitsToDevice should have failed\n"); + + ret = VirtualProtect( (char*)bits, si.dwPageSize, + PAGE_READONLY, &oldprotect); + ok( ret, "VirtualProtect failed\n"); + ret = SetDIBitsToDevice( hdc, 0, 0, 100, 100, 0, 0, 0, 100, bits, + pbmi, DIB_RGB_COLORS); + ok( ret, "SetDIBitsToDevice should have succeeded\n"); + + DeleteDC( hdc); + ReleaseDC(0, hdc0); +} + START_TEST(bitmap) { HMODULE hdll; @@ -2041,4 +2097,5 @@ START_TEST(bitmap) test_GdiAlphaBlend(); test_bitmapinfoheadersize(); test_get16dibits(); + test_badbits(); }