diff --git a/dlls/gdi32/dib.c b/dlls/gdi32/dib.c
index d53b8f2..4149263 100644
--- a/dlls/gdi32/dib.c
+++ b/dlls/gdi32/dib.c
@@ -189,9 +189,24 @@ INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
                        const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
 {
     DC *dc;
+    int nsrcbytes;
 
+    /* Many broken apps pass bad pointers to this function; see bug 7380.
+     * Windows catches this and returns silently, in spite of 
+     * what TheOldNewThing says about crashing being better.
+     */
     if (!bits || !info)
 	return 0;
+    if (info->bmiHeader.biCompression)
+        nsrcbytes = 1;   /* checking start better than nothing */
+    else {
+        int dibpitch = ((widthSrc * info->bmiHeader.biBitCount + 31) &~31) / 8;
+        nsrcbytes = heightSrc * dibpitch;
+        if (nsrcbytes < 0)
+            nsrcbytes = - nsrcbytes;
+    }
+    if (IsBadReadPtr(bits, nsrcbytes))     /* so shoot me */
+        return 0;
 
     if (!(dc = get_dc_ptr( hdc ))) return FALSE;
 
@@ -378,8 +393,24 @@ INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
 {
     INT ret;
     DC *dc;
+    int nsrcbytes;
 
-    if (!bits) return 0;
+    /* Many broken apps pass bad pointers to this function; see bug 7380.
+     * Windows catches this and returns silently, in spite of 
+     * what TheOldNewThing says about crashing being better.
+     */
+    if (!bits || !info)
+	return 0;
+    if (info->bmiHeader.biCompression)
+	nsrcbytes = 1;   /* checking start better than nothing */
+    else {
+	int dibpitch = ((cx * info->bmiHeader.biBitCount + 31) &~31) / 8;
+	nsrcbytes = cy * dibpitch;
+	if (nsrcbytes < 0)
+	    nsrcbytes = - nsrcbytes;
+    }
+    if (IsBadReadPtr(bits, nsrcbytes))     /* so shoot me */
+	return 0;
 
     if (!(dc = get_dc_ptr( hdc ))) return 0;
 
diff --git a/dlls/gdi32/tests/bitmap.c b/dlls/gdi32/tests/bitmap.c
index c31d367..82ac935 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, 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, 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();
 }
