From b8b7b568f1a9ba9e38bc612978bc01782bd804b9 Mon Sep 17 00:00:00 2001 From: MysterD Date: Thu, 15 Jun 2023 20:50:05 -0700 Subject: [PATCH] Add bounds checking to instant warps, and make object collisions dynamic in size --- src/engine/level_script.c | 31 ++++++++++++++++++++++--------- src/engine/surface_load.c | 20 +++++++++++++++++--- src/game/area.c | 2 +- src/game/area.h | 2 ++ 4 files changed, 42 insertions(+), 13 deletions(-) diff --git a/src/engine/level_script.c b/src/engine/level_script.c index 4f351d18..175725a3 100644 --- a/src/engine/level_script.c +++ b/src/engine/level_script.c @@ -574,27 +574,40 @@ static void level_cmd_create_warp_node(void) { } static void level_cmd_create_instant_warp(void) { - s32 i; - struct InstantWarp *warp; + struct InstantWarp *warp = NULL; if (sCurrAreaIndex != -1) { if (gAreas[sCurrAreaIndex].instantWarps == NULL) { gAreas[sCurrAreaIndex].instantWarps = dynamic_pool_alloc(gLevelPool, 4 * sizeof(struct InstantWarp)); - for (i = INSTANT_WARP_INDEX_START; i < INSTANT_WARP_INDEX_STOP; i++) { + for (s32 i = INSTANT_WARP_INDEX_START; i < INSTANT_WARP_INDEX_STOP; i++) { gAreas[sCurrAreaIndex].instantWarps[i].id = 0; } } - warp = gAreas[sCurrAreaIndex].instantWarps + CMD_GET(u8, 2); + u8 warpIndex = CMD_GET(u8, 2); + if (warpIndex >= INSTANT_WARP_INDEX_STOP) { + LOG_ERROR("Instant warp index out of bounds: %u", warpIndex); + sCurrentCmd = CMD_NEXT; + return; + } - warp[0].id = 1; - warp[0].area = CMD_GET(u8, 3); + u8 areaIndex = CMD_GET(u8, 3); + if (areaIndex >= MAX_AREAS) { + LOG_ERROR("Instant warp area index out of bounds: %u", areaIndex); + sCurrentCmd = CMD_NEXT; + return; + } - warp[0].displacement[0] = CMD_GET(s16, 4); - warp[0].displacement[1] = CMD_GET(s16, 6); - warp[0].displacement[2] = CMD_GET(s16, 8); + warp = &gAreas[sCurrAreaIndex].instantWarps[warpIndex]; + + warp->id = 1; + warp->area = areaIndex; + + warp->displacement[0] = CMD_GET(s16, 4); + warp->displacement[1] = CMD_GET(s16, 6); + warp->displacement[2] = CMD_GET(s16, 8); } sCurrentCmd = CMD_NEXT; diff --git a/src/engine/surface_load.c b/src/engine/surface_load.c index 29f08c8b..14eb0cba 100644 --- a/src/engine/surface_load.c +++ b/src/engine/surface_load.c @@ -756,7 +756,21 @@ void load_object_collision_model(void) { if (!gCurrentObject) { return; } if (gCurrentObject->collisionData == NULL) { return; } - s16 vertexData[600]; + s32 numVertices = *gCurrentObject->collisionData; + if (numVertices <= 0) { + LOG_ERROR("Object collisions had invalid vertex count"); + return; + } + + static s32 sVertexDataCount = 0; + static s16* sVertexData = NULL; + + // allocate vertex data + if (numVertices > sVertexDataCount || sVertexData == NULL) { + if (sVertexData) { free(sVertexData); } + sVertexDataCount = numVertices; + sVertexData = malloc(sizeof(s16) * sVertexDataCount); + } s16* collisionData = gCurrentObject->collisionData; f32 tangibleDist = gCurrentObject->oCollisionDistance; @@ -778,11 +792,11 @@ void load_object_collision_model(void) { && (anyPlayerInTangibleRange) && !(gCurrentObject->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM)) { collisionData++; - transform_object_vertices(&collisionData, vertexData); + transform_object_vertices(&collisionData, sVertexData); // TERRAIN_LOAD_CONTINUE acts as an "end" to the terrain data. while (*collisionData != TERRAIN_LOAD_CONTINUE) { - load_object_surfaces(&collisionData, vertexData); + load_object_surfaces(&collisionData, sVertexData); } } diff --git a/src/game/area.c b/src/game/area.c index ef5375d8..4f997031 100644 --- a/src/game/area.c +++ b/src/game/area.c @@ -29,7 +29,7 @@ #include "pc/djui/djui_panel_pause.h" struct SpawnInfo gPlayerSpawnInfos[MAX_PLAYERS]; -struct Area gAreaData[8]; +struct Area gAreaData[MAX_AREAS]; struct WarpTransition gWarpTransition; diff --git a/src/game/area.h b/src/game/area.h index f1a607ca..14b8003c 100644 --- a/src/game/area.h +++ b/src/game/area.h @@ -26,6 +26,8 @@ struct ObjectWarpNode #define INSTANT_WARP_INDEX_START 0x00 // Equal and greater than Surface 0x1B #define INSTANT_WARP_INDEX_STOP 0x04 // Less than Surface 0x1F +#define MAX_AREAS 8 + struct InstantWarp { /*0x00*/ u8 id; // 0 = 0x1B / 1 = 0x1C / 2 = 0x1D / 3 = 0x1E