From 1e40b689b239b560c22a06a24145844d936c57d3 Mon Sep 17 00:00:00 2001 From: hendricks266 Date: Thu, 24 Sep 2015 06:31:55 +0000 Subject: [PATCH] C-CON: Correct handling of size-zero gamearrays: Prevent a crash upon loading a savegame containing them, and allow resizearray to zero. git-svn-id: https://svn.eduke32.com/eduke32@5355 1a8010ca-5511-0410-912e-c29ae57300e0 --- polymer/eduke32/source/gameexec.c | 22 ++++++++++++++-------- polymer/eduke32/source/gamevars.c | 19 +++++++++++++++---- polymer/eduke32/source/savegame.c | 5 +++-- 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/polymer/eduke32/source/gameexec.c b/polymer/eduke32/source/gameexec.c index 80866a591..2159c347d 100644 --- a/polymer/eduke32/source/gameexec.c +++ b/polymer/eduke32/source/gameexec.c @@ -4579,9 +4579,13 @@ finish_qsprintf: int32_t numelts = kfilelength(fil) / sizeof(int32_t); - // NOTE: LunaCON is stricter: if the file has no - // elements, resize the array to size zero. - if (numelts > 0) + if (numelts == 0) + { + Baligned_free(aGameArrays[j].plValues); + aGameArrays[j].plValues = NULL; + aGameArrays[j].size = numelts; + } + else if (numelts > 0) { int32_t numbytes = numelts * sizeof(int32_t); #ifdef BITNESS64 @@ -4644,18 +4648,20 @@ finish_qsprintf: const int32_t newSize = Gv_GetVarX(*insptr++); const int32_t oldSize = aGameArrays[tw].size; - if (newSize > 0 && newSize != oldSize) + if (newSize >= 0 && newSize != oldSize) { // OSD_Printf(OSDTEXT_GREEN "CON_RESIZEARRAY: resizing array %s from %d to %d\n", // aGameArrays[j].szLabel, aGameArrays[j].size, newSize); - intptr_t *const tmpar = (intptr_t *)Xmalloc(GAR_ELTSZ * oldSize); - memcpy(tmpar, aGameArrays[tw].plValues, GAR_ELTSZ * oldSize); + intptr_t *const tmpar = oldSize != 0 ? (intptr_t *)Xmalloc(GAR_ELTSZ * oldSize) : NULL; + if (oldSize != 0) + memcpy(tmpar, aGameArrays[tw].plValues, GAR_ELTSZ * oldSize); Baligned_free(aGameArrays[tw].plValues); - aGameArrays[tw].plValues = (intptr_t *)Xaligned_alloc(ACTOR_VAR_ALIGNMENT, GAR_ELTSZ * newSize); + aGameArrays[tw].plValues = newSize != 0 ? (intptr_t *)Xaligned_alloc(ACTOR_VAR_ALIGNMENT, GAR_ELTSZ * newSize) : NULL; aGameArrays[tw].size = newSize; - memcpy(aGameArrays[tw].plValues, tmpar, GAR_ELTSZ * min(oldSize, newSize)); + if (oldSize != 0) + memcpy(aGameArrays[tw].plValues, tmpar, GAR_ELTSZ * min(oldSize, newSize)); if (newSize > oldSize) memset(&aGameArrays[tw].plValues[oldSize], 0, GAR_ELTSZ * (newSize - oldSize)); } diff --git a/polymer/eduke32/source/gamevars.c b/polymer/eduke32/source/gamevars.c index ce50ed2f1..d0e6b3bbb 100644 --- a/polymer/eduke32/source/gamevars.c +++ b/polymer/eduke32/source/gamevars.c @@ -189,8 +189,14 @@ int32_t Gv_ReadSave(int32_t fil, int32_t newbehav) goto corrupt; hash_add(&h_arrays, aGameArrays[i].szLabel, i, 1); - aGameArrays[i].plValues = (intptr_t *)Xaligned_alloc(ACTOR_VAR_ALIGNMENT, aGameArrays[i].size * GAR_ELTSZ); - if (kdfread(aGameArrays[i].plValues, GAR_ELTSZ * aGameArrays[i].size, 1, fil) < 1) goto corrupt; + intptr_t const asize = aGameArrays[i].size; + if (asize != 0) + { + aGameArrays[i].plValues = (intptr_t *)Xaligned_alloc(ACTOR_VAR_ALIGNMENT, asize * GAR_ELTSZ); + if (kdfread(aGameArrays[i].plValues, GAR_ELTSZ * aGameArrays[i].size, 1, fil) < 1) goto corrupt; + } + else + aGameArrays[i].plValues = NULL; } // Bsprintf(g_szBuf,"CP:%s %d",__FILE__,__LINE__); @@ -466,8 +472,13 @@ int32_t Gv_NewArray(const char *pszLabel, void *arrayptr, intptr_t asize, uint32 if (!(dwFlags & GAMEARRAY_TYPE_MASK)) { Baligned_free(aGameArrays[i].plValues); - aGameArrays[i].plValues = (intptr_t *)Xaligned_alloc(ACTOR_VAR_ALIGNMENT, asize * GAR_ELTSZ); - Bmemset(aGameArrays[i].plValues, 0, asize * GAR_ELTSZ); + if (asize != 0) + { + aGameArrays[i].plValues = (intptr_t *)Xaligned_alloc(ACTOR_VAR_ALIGNMENT, asize * GAR_ELTSZ); + Bmemset(aGameArrays[i].plValues, 0, asize * GAR_ELTSZ); + } + else + aGameArrays[i].plValues = NULL; } else aGameArrays[i].plValues=(intptr_t *)arrayptr; diff --git a/polymer/eduke32/source/savegame.c b/polymer/eduke32/source/savegame.c index 6cbd1a260..5d4524789 100644 --- a/polymer/eduke32/source/savegame.c +++ b/polymer/eduke32/source/savegame.c @@ -1215,9 +1215,10 @@ static void sv_makevarspec() if (aGameArrays[i].dwFlags & GAMEARRAY_READONLY) continue; + intptr_t * const plValues = aGameArrays[i].plValues; svgm_vars[j].flags = 0; - svgm_vars[j].ptr = aGameArrays[i].plValues; - svgm_vars[j].size = sizeof(aGameArrays[0].plValues[0]); + svgm_vars[j].ptr = plValues; + svgm_vars[j].size = plValues == NULL ? 0 : sizeof(aGameArrays[0].plValues[0]); svgm_vars[j].cnt = aGameArrays[i].size; // assumed constant throughout demo, i.e. no RESIZEARRAY j++; }