From aa2ca0376ab186aacd5197eec88017da898112d7 Mon Sep 17 00:00:00 2001 From: Cyd Date: Mon, 10 Aug 2026 15:34:22 -0500 Subject: [PATCH] The camera HUD only reads the slots it filled A Live Cam host launched into a real race took the process down with an access violation. WER put the fault at image offset 0x76239, which with this build's fixed base resolves against the shipped PDB to CameraShipHUDRenderable::Execute - the dereference in the ranking loop. Two defects, both older than Live Cam. playerRank is SPARSE: it is sized for the racing players plus the camera players and filled by playerBitmapIndex - 1, exactly as the constructor's own comment says. But it was allocated with new[], which does not zero, and Execute walked it densely to playerCount and dereferenced every slot. Any bitmap index that nobody claimed was therefore uninitialised heap read as an int*. Live Cam is simply the first thing that can leave a gap at the front. The host takes bitmap index 1 and, being the camera, is not in the "Players" group, so slot 0 was never claimed while playerCount was still 1 and the loop still ran. The arcade never hit it because its camera cabinets sat after the pods in the egg, so slot 0 belonged to a real racer and the dense walk was accidentally safe. So: clear the array on allocation, remember its real length as rankCount, and iterate that while skipping the unclaimed slots. The playerCount bound was wrong on its own terms too - a race whose bitmap indices run past it would have missed the tail. Everything before the crash worked on the first try, which is the other half of the news: with a live racing peer the camera director builds, the camera ship comes up and starts directing. The map-load hang that stopped a camera host before was an artefact of it having no peers. Co-Authored-By: Claude Opus 5 (1M context) --- MUNGA_L4/L4VIDRND.cpp | 21 ++++++++++++++++++++- MUNGA_L4/L4VIDRND.h | 13 +++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/MUNGA_L4/L4VIDRND.cpp b/MUNGA_L4/L4VIDRND.cpp index e183145..f570820 100644 --- a/MUNGA_L4/L4VIDRND.cpp +++ b/MUNGA_L4/L4VIDRND.cpp @@ -2805,6 +2805,7 @@ CameraShipHUDRenderable::CameraShipHUDRenderable(Entity *entity, ExecutionType e // playerRank = NULL; oldPlayerRank = NULL; + rankCount = 0; nameDCS = NULL; rankDCS = NULL; nameInstance = NULL; @@ -2848,6 +2849,18 @@ CameraShipHUDRenderable::CameraShipHUDRenderable(Entity *entity, ExecutionType e Verify(camera_player_count <= MAX_PLAYER_NAMES); playerRank = new (int (*[camera_player_count])); Register_Pointer(playerRank); + // + // Cleared, because the fill below is by bitmap index and leaves + // gaps: with a Live Cam host the racing players start at index 2 + // and nothing ever claims slot 0. new[] does not zero, so those + // gaps were uninitialised heap read as int* - the access + // violation in Execute. + // + rankCount = camera_player_count; + for (int slot = 0; slot < rankCount; ++slot) + { + playerRank[slot] = NULL; + } Player *active_player; if(player_group) { @@ -3095,8 +3108,14 @@ void CameraShipHUDRenderable::Execute() // whenever they change! //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // - for(int ii=0; ii