From f3f04c073ef08125e57c93d6817e7d71ef2e1470 Mon Sep 17 00:00:00 2001 From: mcmartin Date: Mon, 5 May 2003 02:11:09 +0000 Subject: [PATCH] Patch for #377; fixes a dangling-pointer bug in _ReleaseCelData This is triggered by having one thread lock a graphics resource (usually through a StarShipPtr) and then have another thread release it. The Frame data is gone, but pointers to that data (as well as the Drawable itself, of course) remain. If the 'locking' thread then tries to use its Frame data, it will have end up accessing garbage. (The nulling of the DrawablePtr->Frame pointer doesn't help because the Frame itself has been cached.) git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@946 8092fc87-c524-0410-9efc-e669fe64eaf9 --- .../sc2code/libs/graphics/sdl/3do_getbody.c | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/sc2/src/sc2code/libs/graphics/sdl/3do_getbody.c b/sc2/src/sc2code/libs/graphics/sdl/3do_getbody.c index b5225c7c9..5eaff8aa2 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/3do_getbody.c +++ b/sc2/src/sc2code/libs/graphics/sdl/3do_getbody.c @@ -497,7 +497,7 @@ _ReleaseCelData (MEM_HANDLE handle) { DRAWABLEPTR DrawablePtr; int cel_ct; - FRAMEPTR FramePtr; + FRAMEPTR FramePtr = NULL; if ((DrawablePtr = LockDrawable (handle)) == 0) return (FALSE); @@ -506,25 +506,28 @@ _ReleaseCelData (MEM_HANDLE handle) if (DrawablePtr->Frame) { - FramePtr = &DrawablePtr->Frame[cel_ct]; - if (TYPE_GET ((FramePtr-1)->TypeIndexAndFlags) != SCREEN_DRAWABLE) + FramePtr = DrawablePtr->Frame; + if (TYPE_GET (FramePtr->TypeIndexAndFlags) == SCREEN_DRAWABLE) { - while (--FramePtr, cel_ct--) - { - TFB_Image *img = FramePtr->image; - if (img) - { - FramePtr->image = NULL; - TFB_DrawScreen_DeleteImage (img); - } - } + FramePtr = NULL; } - HFree (DrawablePtr->Frame); - DrawablePtr->Frame = NULL; } UnlockDrawable (handle); - mem_release (handle); + if (mem_release (handle) && FramePtr) + { + int i; + for (i = 0; i < cel_ct; i++) + { + TFB_Image *img = FramePtr[i].image; + if (img) + { + FramePtr[i].image = NULL; + TFB_DrawScreen_DeleteImage (img); + } + } + HFree (FramePtr); + } return (TRUE); }