Module: wine Branch: master Commit: cf39adbaa2ad80980f8d8f03a9d8802ef7cbd4fd URL: http://source.winehq.org/git/wine.git/?a=commit;h=cf39adbaa2ad80980f8d8f03a9...
Author: Henri Verbeet hverbeet@codeweavers.com Date: Thu Jun 24 12:10:03 2010 +0200
ddraw: Avoid an integer overflow in IDirectDrawSurfaceImpl_BltFast().
Bug spotted by Iain Arnell, test by Iain Arnell.
---
dlls/ddraw/surface.c | 28 ++++++++++++++++------------ dlls/ddraw/tests/dsurface.c | 8 ++++++++ 2 files changed, 24 insertions(+), 12 deletions(-)
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index bfe83a4..ef7b381 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -2077,9 +2077,13 @@ IDirectDrawSurfaceImpl_BltFast(IDirectDrawSurface7 *iface, { IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface; IDirectDrawSurfaceImpl *src = (IDirectDrawSurfaceImpl *)Source; + DWORD src_w, src_h, dst_w, dst_h; HRESULT hr; TRACE("(%p)->(%d,%d,%p,%p,%d): Relay\n", This, dstx, dsty, Source, rsrc, trans);
+ dst_w = This->surface_desc.dwWidth; + dst_h = This->surface_desc.dwHeight; + /* Source must be != NULL, This is not checked by windows. Windows happily throws a 0xc0000005 * in that case */ @@ -2092,21 +2096,21 @@ IDirectDrawSurfaceImpl_BltFast(IDirectDrawSurface7 *iface, 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; - } + + src_w = rsrc->right - rsrc->left; + src_h = rsrc->bottom - rsrc->top; } 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; - } + src_w = src->surface_desc.dwWidth; + src_h = src->surface_desc.dwHeight; + } + + if (src_w > dst_w || dstx > dst_w - src_w + || src_h > dst_h || dsty > dst_h - src_h) + { + WARN("Destination area out of bounds, returning DDERR_INVALIDRECT.\n"); + return DDERR_INVALIDRECT; }
EnterCriticalSection(&ddraw_cs); diff --git a/dlls/ddraw/tests/dsurface.c b/dlls/ddraw/tests/dsurface.c index bfd5eae..20e8634 100644 --- a/dlls/ddraw/tests/dsurface.c +++ b/dlls/ddraw/tests/dsurface.c @@ -2537,6 +2537,14 @@ static void BltParamTest(void) 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(surface1, -10, 0, surface2, NULL, 0); + ok(hr == DDERR_INVALIDRECT, "BltFast with an offset resulting in an off-surface write returned %08x\n", hr); + hr = IDirectDrawSurface_BltFast(surface1, 0, -10, surface2, NULL, 0); + ok(hr == DDERR_INVALIDRECT, "BltFast with an offset resulting in an off-surface write returned %08x\n", hr); + hr = IDirectDrawSurface_BltFast(surface2, 20, 20, surface1, &valid, 0); + ok(hr == DD_OK, "BltFast from bigger to smaller surface using a valid rectangle and offset 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);