From ef042be5eab24af859eb1550e454319a333456aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20Dub=C3=A9?= Date: Mon, 23 Mar 2026 01:32:26 +0000 Subject: [PATCH] avoid undefined behavior when handling anchor packets (#6393) --- .../Network/Anchor/Packets/DamagePlayer.cpp | 6 ++--- .../Anchor/Packets/EntranceDiscovered.cpp | 2 +- .../Network/Anchor/Packets/GameComplete.cpp | 2 +- soh/soh/Network/Anchor/Packets/GiveItem.cpp | 6 ++--- soh/soh/Network/Anchor/Packets/OcarinaSfx.cpp | 9 +++---- soh/soh/Network/Anchor/Packets/PlayerSfx.cpp | 4 +-- .../Anchor/Packets/RequestTeleport.cpp | 2 +- .../Network/Anchor/Packets/ServerMessage.cpp | 2 +- .../Network/Anchor/Packets/SetCheckStatus.cpp | 6 ++--- soh/soh/Network/Anchor/Packets/SetFlag.cpp | 6 ++--- soh/soh/Network/Anchor/Packets/TeleportTo.cpp | 6 ++--- soh/soh/Network/Anchor/Packets/UnsetFlag.cpp | 6 ++--- .../Anchor/Packets/UpdateBeansCount.cpp | 4 +-- .../Anchor/Packets/UpdateClientState.cpp | 2 +- .../Anchor/Packets/UpdateDungeonItems.cpp | 6 ++--- .../Anchor/Packets/UpdateTeamState.cpp | 27 +++++++++---------- 16 files changed, 47 insertions(+), 49 deletions(-) diff --git a/soh/soh/Network/Anchor/Packets/DamagePlayer.cpp b/soh/soh/Network/Anchor/Packets/DamagePlayer.cpp index e97abea4f..eea1e8175 100644 --- a/soh/soh/Network/Anchor/Packets/DamagePlayer.cpp +++ b/soh/soh/Network/Anchor/Packets/DamagePlayer.cpp @@ -29,7 +29,7 @@ void Anchor::SendPacket_DamagePlayer(u32 clientId, u8 damageEffect, u8 damage) { } void Anchor::HandlePacket_DamagePlayer(nlohmann::json payload) { - uint32_t clientId = payload["clientId"].get(); + uint32_t clientId = payload.at("clientId").get(); if (!clients.contains(clientId) || clients[clientId].player == nullptr) { return; } @@ -44,8 +44,8 @@ void Anchor::HandlePacket_DamagePlayer(nlohmann::json payload) { return; } - u8 damageEffect = payload["damageEffect"].get(); - u8 damage = payload["damage"].get(); + u8 damageEffect = payload.at("damageEffect").get(); + u8 damage = payload.at("damage").get(); self->actor.colChkInfo.damage = damage * 8; // Arbitrary number currently, need to fine tune diff --git a/soh/soh/Network/Anchor/Packets/EntranceDiscovered.cpp b/soh/soh/Network/Anchor/Packets/EntranceDiscovered.cpp index 6669e28a0..85671f0ed 100644 --- a/soh/soh/Network/Anchor/Packets/EntranceDiscovered.cpp +++ b/soh/soh/Network/Anchor/Packets/EntranceDiscovered.cpp @@ -28,6 +28,6 @@ void Anchor::HandlePacket_EntranceDiscovered(nlohmann::json payload) { return; } - u16 entranceIndex = payload["entranceIndex"].get(); + u16 entranceIndex = payload.at("entranceIndex").get(); Entrance_SetEntranceDiscovered(entranceIndex, 1); } diff --git a/soh/soh/Network/Anchor/Packets/GameComplete.cpp b/soh/soh/Network/Anchor/Packets/GameComplete.cpp index aa05a6e64..e8fdaafc3 100644 --- a/soh/soh/Network/Anchor/Packets/GameComplete.cpp +++ b/soh/soh/Network/Anchor/Packets/GameComplete.cpp @@ -26,7 +26,7 @@ void Anchor::SendPacket_GameComplete() { } void Anchor::HandlePacket_GameComplete(nlohmann::json payload) { - uint32_t clientId = payload["clientId"].get(); + uint32_t clientId = payload.at("clientId").get(); if (!clients.contains(clientId)) { return; } diff --git a/soh/soh/Network/Anchor/Packets/GiveItem.cpp b/soh/soh/Network/Anchor/Packets/GiveItem.cpp index fbf048d7d..f957eef02 100644 --- a/soh/soh/Network/Anchor/Packets/GiveItem.cpp +++ b/soh/soh/Network/Anchor/Packets/GiveItem.cpp @@ -49,10 +49,10 @@ void Anchor::HandlePacket_GiveItem(nlohmann::json payload) { return; } - uint32_t clientId = payload["clientId"].get(); + uint32_t clientId = payload.at("clientId").get(); AnchorClient& client = clients[clientId]; - u16 modId = payload["modId"].get(); - u16 getItemId = payload["getItemId"].get(); + u16 modId = payload.at("modId").get(); + u16 getItemId = payload.at("getItemId").get(); GetItemEntry getItemEntry; if (modId == MOD_NONE) { diff --git a/soh/soh/Network/Anchor/Packets/OcarinaSfx.cpp b/soh/soh/Network/Anchor/Packets/OcarinaSfx.cpp index 72eee3c5c..c2b958102 100644 --- a/soh/soh/Network/Anchor/Packets/OcarinaSfx.cpp +++ b/soh/soh/Network/Anchor/Packets/OcarinaSfx.cpp @@ -1,5 +1,4 @@ #include "soh/Network/Anchor/Anchor.h" -#include "soh/Network/Anchor/JsonConversions.hpp" #include #include @@ -39,10 +38,10 @@ void Anchor::SendPacket_OcarinaSfx(uint8_t note, float modulator, int8_t bend) { } void Anchor::HandlePacket_OcarinaSfx(nlohmann::json payload) { - uint32_t clientId = payload["clientId"].get(); - uint8_t note = payload["note"].get(); - float modulator = payload["modulator"].get(); - int8_t bend = payload["bend"].get(); + uint32_t clientId = payload.at("clientId").get(); + uint8_t note = payload.at("note").get(); + float modulator = payload.at("modulator").get(); + int8_t bend = payload.at("bend").get(); if (!clients.contains(clientId) || !clients[clientId].player) { return; diff --git a/soh/soh/Network/Anchor/Packets/PlayerSfx.cpp b/soh/soh/Network/Anchor/Packets/PlayerSfx.cpp index ce4755adf..6dff899eb 100644 --- a/soh/soh/Network/Anchor/Packets/PlayerSfx.cpp +++ b/soh/soh/Network/Anchor/Packets/PlayerSfx.cpp @@ -36,8 +36,8 @@ void Anchor::SendPacket_PlayerSfx(u16 sfxId) { } void Anchor::HandlePacket_PlayerSfx(nlohmann::json payload) { - uint32_t clientId = payload["clientId"].get(); - u16 sfxId = payload["sfxId"].get(); + uint32_t clientId = payload.at("clientId").get(); + u16 sfxId = payload.at("sfxId").get(); if (!clients.contains(clientId) || !clients[clientId].player) { return; diff --git a/soh/soh/Network/Anchor/Packets/RequestTeleport.cpp b/soh/soh/Network/Anchor/Packets/RequestTeleport.cpp index 8bcb1a306..4d9c57263 100644 --- a/soh/soh/Network/Anchor/Packets/RequestTeleport.cpp +++ b/soh/soh/Network/Anchor/Packets/RequestTeleport.cpp @@ -27,7 +27,7 @@ void Anchor::HandlePacket_RequestTeleport(nlohmann::json payload) { return; } - uint32_t clientId = payload["clientId"].get(); + uint32_t clientId = payload.at("clientId").get(); SendPacket_TeleportTo(clientId); } diff --git a/soh/soh/Network/Anchor/Packets/ServerMessage.cpp b/soh/soh/Network/Anchor/Packets/ServerMessage.cpp index 9c1fdc132..e7b119731 100644 --- a/soh/soh/Network/Anchor/Packets/ServerMessage.cpp +++ b/soh/soh/Network/Anchor/Packets/ServerMessage.cpp @@ -12,6 +12,6 @@ void Anchor::HandlePacket_ServerMessage(nlohmann::json payload) { Notification::Emit({ .prefix = "Server:", .prefixColor = ImVec4(1.0f, 0.5f, 0.5f, 1.0f), - .message = payload["message"].get(), + .message = payload.at("message").get(), }); } diff --git a/soh/soh/Network/Anchor/Packets/SetCheckStatus.cpp b/soh/soh/Network/Anchor/Packets/SetCheckStatus.cpp index fb1c70dc9..ee48f247a 100644 --- a/soh/soh/Network/Anchor/Packets/SetCheckStatus.cpp +++ b/soh/soh/Network/Anchor/Packets/SetCheckStatus.cpp @@ -38,9 +38,9 @@ void Anchor::HandlePacket_SetCheckStatus(nlohmann::json payload) { auto randoContext = Rando::Context::GetInstance(); - RandomizerCheck rc = payload["rc"].get(); - RandomizerCheckStatus status = payload["status"].get(); - bool skipped = payload["skipped"].get(); + RandomizerCheck rc = payload.at("rc").get(); + RandomizerCheckStatus status = payload.at("status").get(); + bool skipped = payload.at("skipped").get(); isResultOfHandling = true; diff --git a/soh/soh/Network/Anchor/Packets/SetFlag.cpp b/soh/soh/Network/Anchor/Packets/SetFlag.cpp index 3468bab01..1cabfcea7 100644 --- a/soh/soh/Network/Anchor/Packets/SetFlag.cpp +++ b/soh/soh/Network/Anchor/Packets/SetFlag.cpp @@ -37,9 +37,9 @@ void Anchor::HandlePacket_SetFlag(nlohmann::json payload) { return; } - s16 sceneNum = payload["sceneNum"].get(); - s16 flagType = payload["flagType"].get(); - s16 flag = payload["flag"].get(); + s16 sceneNum = payload.at("sceneNum").get(); + s16 flagType = payload.at("flagType").get(); + s16 flag = payload.at("flag").get(); if (sceneNum == SCENE_ID_MAX) { auto effect = new GameInteractionEffect::SetFlag(); diff --git a/soh/soh/Network/Anchor/Packets/TeleportTo.cpp b/soh/soh/Network/Anchor/Packets/TeleportTo.cpp index 1d50be449..c23ce7304 100644 --- a/soh/soh/Network/Anchor/Packets/TeleportTo.cpp +++ b/soh/soh/Network/Anchor/Packets/TeleportTo.cpp @@ -37,9 +37,9 @@ void Anchor::HandlePacket_TeleportTo(nlohmann::json payload) { return; } - s32 entranceIndex = payload["entranceIndex"].get(); - s8 roomIndex = payload["roomIndex"].get(); - PosRot posRot = payload["posRot"].get(); + s32 entranceIndex = payload.at("entranceIndex").get(); + s8 roomIndex = payload.at("roomIndex").get(); + PosRot posRot = payload.at("posRot").get(); gPlayState->nextEntranceIndex = entranceIndex; gPlayState->transitionTrigger = TRANS_TRIGGER_START; diff --git a/soh/soh/Network/Anchor/Packets/UnsetFlag.cpp b/soh/soh/Network/Anchor/Packets/UnsetFlag.cpp index cf2fbf5d4..6943c1a6b 100644 --- a/soh/soh/Network/Anchor/Packets/UnsetFlag.cpp +++ b/soh/soh/Network/Anchor/Packets/UnsetFlag.cpp @@ -37,9 +37,9 @@ void Anchor::HandlePacket_UnsetFlag(nlohmann::json payload) { return; } - s16 sceneNum = payload["sceneNum"].get(); - s16 flagType = payload["flagType"].get(); - s16 flag = payload["flag"].get(); + s16 sceneNum = payload.at("sceneNum").get(); + s16 flagType = payload.at("flagType").get(); + s16 flag = payload.at("flag").get(); if (sceneNum == SCENE_ID_MAX) { auto effect = new GameInteractionEffect::UnsetFlag(); diff --git a/soh/soh/Network/Anchor/Packets/UpdateBeansCount.cpp b/soh/soh/Network/Anchor/Packets/UpdateBeansCount.cpp index 976c7cc24..c536459fb 100644 --- a/soh/soh/Network/Anchor/Packets/UpdateBeansCount.cpp +++ b/soh/soh/Network/Anchor/Packets/UpdateBeansCount.cpp @@ -34,6 +34,6 @@ void Anchor::HandlePacket_UpdateBeansCount(nlohmann::json payload) { return; } - AMMO(ITEM_BEAN) = payload["amount"].get(); - BEANS_BOUGHT = payload["amountBought"].get(); + AMMO(ITEM_BEAN) = payload.at("amount").get(); + BEANS_BOUGHT = payload.at("amountBought").get(); } diff --git a/soh/soh/Network/Anchor/Packets/UpdateClientState.cpp b/soh/soh/Network/Anchor/Packets/UpdateClientState.cpp index 3099da84a..7beb83ce0 100644 --- a/soh/soh/Network/Anchor/Packets/UpdateClientState.cpp +++ b/soh/soh/Network/Anchor/Packets/UpdateClientState.cpp @@ -54,7 +54,7 @@ void Anchor::SendPacket_UpdateClientState() { } void Anchor::HandlePacket_UpdateClientState(nlohmann::json payload) { - uint32_t clientId = payload["clientId"].get(); + uint32_t clientId = payload.at("clientId").get(); if (clients.contains(clientId)) { AnchorClient client = payload["state"].get(); diff --git a/soh/soh/Network/Anchor/Packets/UpdateDungeonItems.cpp b/soh/soh/Network/Anchor/Packets/UpdateDungeonItems.cpp index 9e0a43200..a994b564c 100644 --- a/soh/soh/Network/Anchor/Packets/UpdateDungeonItems.cpp +++ b/soh/soh/Network/Anchor/Packets/UpdateDungeonItems.cpp @@ -32,7 +32,7 @@ void Anchor::HandlePacket_UpdateDungeonItems(nlohmann::json payload) { return; } - u16 mapIndex = payload["mapIndex"].get(); - gSaveContext.inventory.dungeonItems[mapIndex] = payload["dungeonItems"].get(); - gSaveContext.inventory.dungeonKeys[mapIndex] = payload["dungeonKeys"].get(); + u16 mapIndex = payload.at("mapIndex").get(); + gSaveContext.inventory.dungeonItems[mapIndex] = payload.at("dungeonItems").get(); + gSaveContext.inventory.dungeonKeys[mapIndex] = payload.at("dungeonKeys").get(); } diff --git a/soh/soh/Network/Anchor/Packets/UpdateTeamState.cpp b/soh/soh/Network/Anchor/Packets/UpdateTeamState.cpp index 9e9169779..4fedfcdc5 100644 --- a/soh/soh/Network/Anchor/Packets/UpdateTeamState.cpp +++ b/soh/soh/Network/Anchor/Packets/UpdateTeamState.cpp @@ -2,8 +2,6 @@ #include "soh/Network/Anchor/JsonConversions.hpp" #include #include -#include "soh/Enhancements/randomizer/entrance.h" -#include "soh/Enhancements/randomizer/dungeon.h" #include "soh/OTRGlobals.h" #include "soh/Notification/Notification.h" @@ -125,8 +123,9 @@ void Anchor::HandlePacket_UpdateTeamState(nlohmann::json payload) { } isHandlingUpdateTeamState = true; - // This can happen in between file select and the game starting, so we cant use this check, but we need to ensure we - // be careful to wrap PlayState usage in this check + // This can happen in between file select and the game starting, so we can't use this check, but we need to ensure + // we be careful to wrap PlayState usage in this check + // // if (!IsSaveLoaded()) { // return; // } @@ -224,24 +223,24 @@ void Anchor::HandlePacket_UpdateTeamState(nlohmann::json payload) { auto randoContext = Rando::Context::GetInstance(); for (int i = 0; i < RC_MAX; i++) { + auto itemLocation = payload["state"]["rando"].at("itemLocations").at(i); // randoContext->GetItemLocation(i)->RefPlacedItem() = - // payload["state"]["rando"]["itemLocations"][i]["rgID"].get(); + // itemLocation.at("rgID").get(); OTRGlobals::Instance->gRandoContext->GetItemLocation(i)->SetCheckStatus( - payload["state"]["rando"]["itemLocations"][i][0].get()); - OTRGlobals::Instance->gRandoContext->GetItemLocation(i)->SetIsSkipped( - payload["state"]["rando"]["itemLocations"][i][1].get()); + itemLocation.at(0).get()); + OTRGlobals::Instance->gRandoContext->GetItemLocation(i)->SetIsSkipped(itemLocation.at(1).get()); - // if (payload["state"]["rando"]["itemLocations"][i].contains("fakeRgID")) { + // if (itemLocation.contains("fakeRgID")) { // randoContext->overrides.emplace(static_cast(i), // Rando::ItemOverride(static_cast(i), - // payload["state"]["rando"]["itemLocations"][i]["fakeRgID"].get())); + // itemLocation.at("fakeRgID").get())); // randoContext->GetItemOverride(i).GetTrickName().english = - // payload["state"]["rando"]["itemLocations"][i]["trickName"]["english"].get(); + // itemLocation.at("trickName").at("english").get(); // randoContext->GetItemOverride(i).GetTrickName().french = - // payload["state"]["rando"]["itemLocations"][i]["trickName"]["french"].get(); + // itemLocation.at("trickName").at("french").get(); // } - // if (payload["state"]["rando"]["itemLocations"][i].contains("price")) { - // u16 price = payload["state"]["rando"]["itemLocations"][i]["price"].get(); + // if (itemLocation.contains("price")) { + // u16 price = itemLocation.at("price"].get(); // if (price > 0) { // randoContext->GetItemLocation(i)->SetCustomPrice(price); // }