Stefan Dösinger : ddraw: Check the validy of IDirectDrawSurface::BltFast parameters.

Alexandre Julliard julliard at wine.codeweavers.com
Thu May 31 08:33:39 CDT 2007


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

Author: Stefan Dösinger <stefandoesinger at gmx.at>
Date:   Thu May 24 22:24:00 2007 +0200

ddraw: Check the validy of IDirectDrawSurface::BltFast parameters.

---

 dlls/ddraw/surface.c        |   29 ++++++++++++++++++++++
 dlls/ddraw/tests/dsurface.c |   57 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 86 insertions(+), 0 deletions(-)

diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c
index 62e4550..2baac81 100644
--- a/dlls/ddraw/surface.c
+++ b/dlls/ddraw/surface.c
@@ -2027,6 +2027,35 @@ IDirectDrawSurfaceImpl_BltFast(IDirectDrawSurface7 *iface,
     IDirectDrawSurfaceImpl *src = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, Source);
     TRACE("(%p)->(%d,%d,%p,%p,%d): Relay\n", This, dstx, dsty, Source, rsrc, trans);
 
+    /* Source must be != NULL, This is not checked by windows. Windows happily throws a 0xc0000005
+     * in that case
+     */
+    if(rsrc)
+    {
+        if(rsrc->top > rsrc->bottom || rsrc->left > rsrc->right ||
+           rsrc->right > src->surface_desc.dwWidth ||
+           rsrc->bottom > src->surface_desc.dwHeight)
+        {
+            WARN("Source rectangle is invalid, returning DDERR_INVALIDRECT\n");
+            return DDERR_INVALIDRECT;
+        }
+        if(dstx + rsrc->right - rsrc->left > This->surface_desc.dwWidth ||
+           dsty + rsrc->bottom - rsrc->top > This->surface_desc.dwHeight)
+        {
+            WARN("Destination area out of bounds, returning DDERR_INVALIDRECT\n");
+            return DDERR_INVALIDRECT;
+        }
+    }
+    else
+    {
+        if(dstx + src->surface_desc.dwWidth > This->surface_desc.dwWidth ||
+           dsty + src->surface_desc.dwHeight > This->surface_desc.dwHeight)
+        {
+            WARN("Destination area out of bounds, returning DDERR_INVALIDRECT\n");
+            return DDERR_INVALIDRECT;
+        }
+    }
+
     EnterCriticalSection(&ddraw_cs);
     hr = IWineD3DSurface_BltFast(This->WineD3DSurface,
                                  dstx, dsty,
diff --git a/dlls/ddraw/tests/dsurface.c b/dlls/ddraw/tests/dsurface.c
index adafb87..449e49f 100644
--- a/dlls/ddraw/tests/dsurface.c
+++ b/dlls/ddraw/tests/dsurface.c
@@ -2203,6 +2203,62 @@ static void PrivateDataTest(void)
     ok(ref2 == ref, "Object reference is %d, expected %d\n", ref2, ref);
 }
 
+static void BltParamTest(void)
+{
+    IDirectDrawSurface *surface1 = NULL, *surface2 = NULL;
+    DDSURFACEDESC desc;
+    HRESULT hr;
+    RECT valid = {10, 10, 20, 20};
+    RECT invalid1 = {20, 10, 10, 20};
+    RECT invalid2 = {20, 20, 20, 20};
+    RECT invalid3 = {-1, -1, 20, 20};
+    RECT invalid4 = {60, 60, 70, 70};
+
+    memset(&desc, 0, sizeof(desc));
+    desc.dwSize = sizeof(desc);
+    desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
+    desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
+    desc.dwHeight = 128;
+    desc.dwWidth = 128;
+    hr = IDirectDraw_CreateSurface(lpDD, &desc, &surface1, NULL);
+    ok(hr == DD_OK, "Creating an offscreen plain surface failed with %08x\n", hr);
+
+    desc.dwHeight = 64;
+    desc.dwWidth = 64;
+    hr = IDirectDraw_CreateSurface(lpDD, &desc, &surface2, NULL);
+    ok(hr == DD_OK, "Creating an offscreen plain surface failed with %08x\n", hr);
+
+    if(0)
+    {
+        /* This crashes */
+        hr = IDirectDrawSurface_BltFast(surface1, 0, 0, NULL, NULL, 0);
+        ok(hr == DD_OK, "BltFast from NULL surface returned %08x\n", hr);
+    }
+    hr = IDirectDrawSurface_BltFast(surface1, 0, 0, surface2, NULL, 0);
+    ok(hr == DD_OK, "BltFast from smaller to bigger surface returned %08x\n", hr);
+    hr = IDirectDrawSurface_BltFast(surface2, 0, 0, surface1, NULL, 0);
+    ok(hr == DDERR_INVALIDRECT, "BltFast from bigger to smaller surface returned %08x\n", hr);
+    hr = IDirectDrawSurface_BltFast(surface2, 0, 0, surface1, &valid, 0);
+    ok(hr == DD_OK, "BltFast from bigger to smaller surface using a valid rectangle returned %08x\n", hr);
+    hr = IDirectDrawSurface_BltFast(surface2, 60, 60, surface1, &valid, 0);
+    ok(hr == DDERR_INVALIDRECT, "BltFast with a rectangle resulting in an off-surface write returned %08x\n", hr);
+    hr = IDirectDrawSurface_BltFast(surface1, 90, 90, surface2, NULL, 0);
+    ok(hr == DDERR_INVALIDRECT, "BltFast with a rectangle resulting in an off-surface write returned %08x\n", hr);
+    hr = IDirectDrawSurface_BltFast(surface2, 0, 0, surface1, &invalid1, 0);
+    ok(hr == DDERR_INVALIDRECT, "BltFast with invalid rectangle 1 returned %08x\n", hr);
+    hr = IDirectDrawSurface_BltFast(surface2, 0, 0, surface1, &invalid2, 0);
+    ok(hr == DDERR_INVALIDRECT, "BltFast with invalid rectangle 2 returned %08x\n", hr);
+    hr = IDirectDrawSurface_BltFast(surface2, 0, 0, surface1, &invalid3, 0);
+    ok(hr == DDERR_INVALIDRECT, "BltFast with invalid rectangle 3 returned %08x\n", hr);
+    hr = IDirectDrawSurface_BltFast(surface1, 0, 0, surface2, &invalid4, 0);
+    ok(hr == DDERR_INVALIDRECT, "BltFast with invalid rectangle 3 returned %08x\n", hr);
+    hr = IDirectDrawSurface_BltFast(surface1, 0, 0, surface1, NULL, 0);
+    ok(hr == DD_OK, "BltFast blitting a surface onto itself returned %08x\n", hr);
+
+    IDirectDrawSurface_Release(surface1);
+    IDirectDrawSurface_Release(surface2);
+}
+
 START_TEST(dsurface)
 {
     if (!CreateDirectDraw())
@@ -2222,5 +2278,6 @@ START_TEST(dsurface)
     CompressedTest();
     SizeTest();
     PrivateDataTest();
+    BltParamTest();
     ReleaseDirectDraw();
 }




More information about the wine-cvs mailing list