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
This commit is contained in:
mcmartin
2003-05-05 02:11:09 +00:00
parent eabc641b5a
commit f3f04c073e
+18 -15
View File
@@ -497,7 +497,7 @@ _ReleaseCelData (MEM_HANDLE handle)
{ {
DRAWABLEPTR DrawablePtr; DRAWABLEPTR DrawablePtr;
int cel_ct; int cel_ct;
FRAMEPTR FramePtr; FRAMEPTR FramePtr = NULL;
if ((DrawablePtr = LockDrawable (handle)) == 0) if ((DrawablePtr = LockDrawable (handle)) == 0)
return (FALSE); return (FALSE);
@@ -506,25 +506,28 @@ _ReleaseCelData (MEM_HANDLE handle)
if (DrawablePtr->Frame) if (DrawablePtr->Frame)
{ {
FramePtr = &DrawablePtr->Frame[cel_ct]; FramePtr = DrawablePtr->Frame;
if (TYPE_GET ((FramePtr-1)->TypeIndexAndFlags) != SCREEN_DRAWABLE) if (TYPE_GET (FramePtr->TypeIndexAndFlags) == SCREEN_DRAWABLE)
{ {
while (--FramePtr, cel_ct--) FramePtr = NULL;
{
TFB_Image *img = FramePtr->image;
if (img)
{
FramePtr->image = NULL;
TFB_DrawScreen_DeleteImage (img);
} }
} }
}
HFree (DrawablePtr->Frame);
DrawablePtr->Frame = NULL;
}
UnlockDrawable (handle); 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); return (TRUE);
} }