From 4df9749570994e3fd6e8d1f77c3b3c4bc1381b59 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Tue, 15 Aug 2023 03:28:37 +0200 Subject: [PATCH] Fix FreeMipmapColormap Crash Backport from SRB2 See: https://git.do.srb2.org/STJr/SRB2/-/commit/e9e0683d5efa1c21b0da5d698acd124421c90c42 Credits go to Lactozilla --- src/hardware/hw_cache.c | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index eed592af..35472b85 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -479,14 +479,39 @@ void HWR_InitTextureCache(void) // Callback function for HWR_FreeTextureCache. static void FreeMipmapColormap(INT32 patchnum, void *patch) { - GLPatch_t* const grpatch = patch; + GLPatch_t* const pat = patch; (void)patchnum; //unused - while (grpatch->mipmap->nextcolormap) + + // The patch must be valid, obviously + if (!pat) + return; + + // The mipmap must be valid, obviously + while (pat->mipmap) { - GLMipmap_t *grmip = grpatch->mipmap->nextcolormap; - grpatch->mipmap->nextcolormap = grmip->nextcolormap; - if (grmip->grInfo.data) Z_Free(grmip->grInfo.data); - free(grmip); + // Confusing at first, but pat->mipmap->nextcolormap + // at the beginning of the loop is the first colormap + // from the linked list of colormaps. + GLMipmap_t *next = NULL; + + // No mipmap in this patch, break out of the loop. + if (!pat->mipmap) + break; + + // No colormap mipmap either. + if (!pat->mipmap->nextcolormap) + break; + + // Set the first colormap to the one that comes after it. + next = pat->mipmap->nextcolormap; + pat->mipmap->nextcolormap = next->nextcolormap; + + // Free image data from memory. + if (next->grInfo.data) + Z_Free(next->grInfo.data); + + // Free the old colormap from memory. + free(next); } } @@ -503,7 +528,7 @@ void HWR_FreeTextureCache(void) // Alam: free the Z_Blocks before freeing it's users - // free all skin after each level: must be done after pfnClearMipMapCache! + // free all patch colormaps after each level: must be done after ClearMipMapCache! for (i = 0; i < numwadfiles; i++) M_AATreeIterate(wadfiles[i]->hwrcache, FreeMipmapColormap);