Fix U_IDLE asset error from cutscene item pointer aliasing
cutsceneCutsceneResolve and cutsceneSystemLoad could be called with a name/path pointer that aliases into CUTSCENE_SYSTEM.loadedItems (e.g. a CUTSCENE item's own name field). cutsceneLoadParse then overwrites that same buffer while loading the target cutscene, so the subsequent stringCopy into loadedFile read stale, corrupted memory. Copy the name/path into a local buffer before use in both functions.
This commit is contained in:
@@ -128,8 +128,19 @@ void cutsceneSystemInsertCutscene(const cutscene_t *cutscene) {
|
|||||||
void cutsceneSystemLoad(const char_t *file) {
|
void cutsceneSystemLoad(const char_t *file) {
|
||||||
assertNotNull(file, "File cannot be NULL");
|
assertNotNull(file, "File cannot be NULL");
|
||||||
|
|
||||||
|
// Copy file out before it can be invalidated - every caller today
|
||||||
|
// passes a string literal, but file could in principle point into
|
||||||
|
// CUTSCENE_SYSTEM.loadedItems (a running item's own name field, if the
|
||||||
|
// running cutscene is loadedScene), which both cutsceneLoadParse and
|
||||||
|
// cutsceneSystemStartCutscene below overwrite/re-enter (see
|
||||||
|
// cutsceneCutsceneResolve's matching comment for the exact bug this
|
||||||
|
// guards against - initial.jsonc's closing CUTSCENE item into
|
||||||
|
// main_menu.jsonc hit it there).
|
||||||
|
char_t fileCopy[ASSET_FILE_NAME_MAX];
|
||||||
|
stringCopy(fileCopy, file, ASSET_FILE_NAME_MAX - 1);
|
||||||
|
|
||||||
errorret_t result = cutsceneLoadParse(
|
errorret_t result = cutsceneLoadParse(
|
||||||
file, &CUTSCENE_SYSTEM.loadedScene, CUTSCENE_SYSTEM.loadedItems,
|
fileCopy, &CUTSCENE_SYSTEM.loadedScene, CUTSCENE_SYSTEM.loadedItems,
|
||||||
CUTSCENE_LOADED_ITEMS_MAX
|
CUTSCENE_LOADED_ITEMS_MAX
|
||||||
);
|
);
|
||||||
if(errorIsNotOk(result)) {
|
if(errorIsNotOk(result)) {
|
||||||
@@ -139,7 +150,7 @@ void cutsceneSystemLoad(const char_t *file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cutsceneSystemStartCutscene(&CUTSCENE_SYSTEM.loadedScene);
|
cutsceneSystemStartCutscene(&CUTSCENE_SYSTEM.loadedScene);
|
||||||
stringCopy(CUTSCENE_SYSTEM.loadedFile, file, ASSET_FILE_NAME_MAX - 1);
|
stringCopy(CUTSCENE_SYSTEM.loadedFile, fileCopy, ASSET_FILE_NAME_MAX - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cutsceneRestart(void) {
|
void cutsceneRestart(void) {
|
||||||
|
|||||||
@@ -430,8 +430,19 @@ bool_t cutsceneCutsceneUpdate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
cutscene_t * cutsceneCutsceneResolve(const char_t *name) {
|
cutscene_t * cutsceneCutsceneResolve(const char_t *name) {
|
||||||
|
// Copy name out before it can be invalidated: this is commonly called
|
||||||
|
// with a pointer into CUTSCENE_SYSTEM.loadedItems itself (a running
|
||||||
|
// CUTSCENE/INSERT item's own cutsceneRef.name/insert.name field, when
|
||||||
|
// the running cutscene IS loadedScene, e.g. initial.jsonc's closing
|
||||||
|
// CUTSCENE item into main_menu.jsonc) - cutsceneLoadParse below parses
|
||||||
|
// straight into that same shared loadedItems buffer, overwriting the
|
||||||
|
// very memory name points into with the target cutscene's own first
|
||||||
|
// item before this function is done reading name.
|
||||||
|
char_t nameCopy[ASSET_FILE_NAME_MAX];
|
||||||
|
stringCopy(nameCopy, name, ASSET_FILE_NAME_MAX - 1);
|
||||||
|
|
||||||
errorret_t result = cutsceneLoadParse(
|
errorret_t result = cutsceneLoadParse(
|
||||||
name, &CUTSCENE_SYSTEM.loadedScene, CUTSCENE_SYSTEM.loadedItems,
|
nameCopy, &CUTSCENE_SYSTEM.loadedScene, CUTSCENE_SYSTEM.loadedItems,
|
||||||
CUTSCENE_LOADED_ITEMS_MAX
|
CUTSCENE_LOADED_ITEMS_MAX
|
||||||
);
|
);
|
||||||
if(errorIsNotOk(result)) {
|
if(errorIsNotOk(result)) {
|
||||||
@@ -444,7 +455,7 @@ cutscene_t * cutsceneCutsceneResolve(const char_t *name) {
|
|||||||
// source the same way it does - cutsceneGoTo needs this to reload the
|
// source the same way it does - cutsceneGoTo needs this to reload the
|
||||||
// untouched original when jumping to a marker behind the current
|
// untouched original when jumping to a marker behind the current
|
||||||
// position (see cutsceneGoTo's doc comment).
|
// position (see cutsceneGoTo's doc comment).
|
||||||
stringCopy(CUTSCENE_SYSTEM.loadedFile, name, ASSET_FILE_NAME_MAX - 1);
|
stringCopy(CUTSCENE_SYSTEM.loadedFile, nameCopy, ASSET_FILE_NAME_MAX - 1);
|
||||||
|
|
||||||
return &CUTSCENE_SYSTEM.loadedScene;
|
return &CUTSCENE_SYSTEM.loadedScene;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user