avoid undefined behavior when handling anchor packets (#6393)

This commit is contained in:
Philip Dubé
2026-03-23 01:32:26 +00:00
committed by GitHub
parent 0498d36428
commit ef042be5ea
16 changed files with 47 additions and 49 deletions

View File

@@ -29,7 +29,7 @@ void Anchor::SendPacket_DamagePlayer(u32 clientId, u8 damageEffect, u8 damage) {
} }
void Anchor::HandlePacket_DamagePlayer(nlohmann::json payload) { void Anchor::HandlePacket_DamagePlayer(nlohmann::json payload) {
uint32_t clientId = payload["clientId"].get<uint32_t>(); uint32_t clientId = payload.at("clientId").get<uint32_t>();
if (!clients.contains(clientId) || clients[clientId].player == nullptr) { if (!clients.contains(clientId) || clients[clientId].player == nullptr) {
return; return;
} }
@@ -44,8 +44,8 @@ void Anchor::HandlePacket_DamagePlayer(nlohmann::json payload) {
return; return;
} }
u8 damageEffect = payload["damageEffect"].get<u8>(); u8 damageEffect = payload.at("damageEffect").get<u8>();
u8 damage = payload["damage"].get<u8>(); u8 damage = payload.at("damage").get<u8>();
self->actor.colChkInfo.damage = damage * 8; // Arbitrary number currently, need to fine tune self->actor.colChkInfo.damage = damage * 8; // Arbitrary number currently, need to fine tune

View File

@@ -28,6 +28,6 @@ void Anchor::HandlePacket_EntranceDiscovered(nlohmann::json payload) {
return; return;
} }
u16 entranceIndex = payload["entranceIndex"].get<u16>(); u16 entranceIndex = payload.at("entranceIndex").get<u16>();
Entrance_SetEntranceDiscovered(entranceIndex, 1); Entrance_SetEntranceDiscovered(entranceIndex, 1);
} }

View File

@@ -26,7 +26,7 @@ void Anchor::SendPacket_GameComplete() {
} }
void Anchor::HandlePacket_GameComplete(nlohmann::json payload) { void Anchor::HandlePacket_GameComplete(nlohmann::json payload) {
uint32_t clientId = payload["clientId"].get<uint32_t>(); uint32_t clientId = payload.at("clientId").get<uint32_t>();
if (!clients.contains(clientId)) { if (!clients.contains(clientId)) {
return; return;
} }

View File

@@ -49,10 +49,10 @@ void Anchor::HandlePacket_GiveItem(nlohmann::json payload) {
return; return;
} }
uint32_t clientId = payload["clientId"].get<uint32_t>(); uint32_t clientId = payload.at("clientId").get<uint32_t>();
AnchorClient& client = clients[clientId]; AnchorClient& client = clients[clientId];
u16 modId = payload["modId"].get<u16>(); u16 modId = payload.at("modId").get<u16>();
u16 getItemId = payload["getItemId"].get<u16>(); u16 getItemId = payload.at("getItemId").get<u16>();
GetItemEntry getItemEntry; GetItemEntry getItemEntry;
if (modId == MOD_NONE) { if (modId == MOD_NONE) {

View File

@@ -1,5 +1,4 @@
#include "soh/Network/Anchor/Anchor.h" #include "soh/Network/Anchor/Anchor.h"
#include "soh/Network/Anchor/JsonConversions.hpp"
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <libultraship/libultraship.h> #include <libultraship/libultraship.h>
@@ -39,10 +38,10 @@ void Anchor::SendPacket_OcarinaSfx(uint8_t note, float modulator, int8_t bend) {
} }
void Anchor::HandlePacket_OcarinaSfx(nlohmann::json payload) { void Anchor::HandlePacket_OcarinaSfx(nlohmann::json payload) {
uint32_t clientId = payload["clientId"].get<uint32_t>(); uint32_t clientId = payload.at("clientId").get<uint32_t>();
uint8_t note = payload["note"].get<uint8_t>(); uint8_t note = payload.at("note").get<uint8_t>();
float modulator = payload["modulator"].get<float>(); float modulator = payload.at("modulator").get<float>();
int8_t bend = payload["bend"].get<int8_t>(); int8_t bend = payload.at("bend").get<int8_t>();
if (!clients.contains(clientId) || !clients[clientId].player) { if (!clients.contains(clientId) || !clients[clientId].player) {
return; return;

View File

@@ -36,8 +36,8 @@ void Anchor::SendPacket_PlayerSfx(u16 sfxId) {
} }
void Anchor::HandlePacket_PlayerSfx(nlohmann::json payload) { void Anchor::HandlePacket_PlayerSfx(nlohmann::json payload) {
uint32_t clientId = payload["clientId"].get<uint32_t>(); uint32_t clientId = payload.at("clientId").get<uint32_t>();
u16 sfxId = payload["sfxId"].get<u16>(); u16 sfxId = payload.at("sfxId").get<u16>();
if (!clients.contains(clientId) || !clients[clientId].player) { if (!clients.contains(clientId) || !clients[clientId].player) {
return; return;

View File

@@ -27,7 +27,7 @@ void Anchor::HandlePacket_RequestTeleport(nlohmann::json payload) {
return; return;
} }
uint32_t clientId = payload["clientId"].get<uint32_t>(); uint32_t clientId = payload.at("clientId").get<uint32_t>();
SendPacket_TeleportTo(clientId); SendPacket_TeleportTo(clientId);
} }

View File

@@ -12,6 +12,6 @@ void Anchor::HandlePacket_ServerMessage(nlohmann::json payload) {
Notification::Emit({ Notification::Emit({
.prefix = "Server:", .prefix = "Server:",
.prefixColor = ImVec4(1.0f, 0.5f, 0.5f, 1.0f), .prefixColor = ImVec4(1.0f, 0.5f, 0.5f, 1.0f),
.message = payload["message"].get<std::string>(), .message = payload.at("message").get<std::string>(),
}); });
} }

View File

@@ -38,9 +38,9 @@ void Anchor::HandlePacket_SetCheckStatus(nlohmann::json payload) {
auto randoContext = Rando::Context::GetInstance(); auto randoContext = Rando::Context::GetInstance();
RandomizerCheck rc = payload["rc"].get<RandomizerCheck>(); RandomizerCheck rc = payload.at("rc").get<RandomizerCheck>();
RandomizerCheckStatus status = payload["status"].get<RandomizerCheckStatus>(); RandomizerCheckStatus status = payload.at("status").get<RandomizerCheckStatus>();
bool skipped = payload["skipped"].get<bool>(); bool skipped = payload.at("skipped").get<bool>();
isResultOfHandling = true; isResultOfHandling = true;

View File

@@ -37,9 +37,9 @@ void Anchor::HandlePacket_SetFlag(nlohmann::json payload) {
return; return;
} }
s16 sceneNum = payload["sceneNum"].get<s16>(); s16 sceneNum = payload.at("sceneNum").get<s16>();
s16 flagType = payload["flagType"].get<s16>(); s16 flagType = payload.at("flagType").get<s16>();
s16 flag = payload["flag"].get<s16>(); s16 flag = payload.at("flag").get<s16>();
if (sceneNum == SCENE_ID_MAX) { if (sceneNum == SCENE_ID_MAX) {
auto effect = new GameInteractionEffect::SetFlag(); auto effect = new GameInteractionEffect::SetFlag();

View File

@@ -37,9 +37,9 @@ void Anchor::HandlePacket_TeleportTo(nlohmann::json payload) {
return; return;
} }
s32 entranceIndex = payload["entranceIndex"].get<s32>(); s32 entranceIndex = payload.at("entranceIndex").get<s32>();
s8 roomIndex = payload["roomIndex"].get<s8>(); s8 roomIndex = payload.at("roomIndex").get<s8>();
PosRot posRot = payload["posRot"].get<PosRot>(); PosRot posRot = payload.at("posRot").get<PosRot>();
gPlayState->nextEntranceIndex = entranceIndex; gPlayState->nextEntranceIndex = entranceIndex;
gPlayState->transitionTrigger = TRANS_TRIGGER_START; gPlayState->transitionTrigger = TRANS_TRIGGER_START;

View File

@@ -37,9 +37,9 @@ void Anchor::HandlePacket_UnsetFlag(nlohmann::json payload) {
return; return;
} }
s16 sceneNum = payload["sceneNum"].get<s16>(); s16 sceneNum = payload.at("sceneNum").get<s16>();
s16 flagType = payload["flagType"].get<s16>(); s16 flagType = payload.at("flagType").get<s16>();
s16 flag = payload["flag"].get<s16>(); s16 flag = payload.at("flag").get<s16>();
if (sceneNum == SCENE_ID_MAX) { if (sceneNum == SCENE_ID_MAX) {
auto effect = new GameInteractionEffect::UnsetFlag(); auto effect = new GameInteractionEffect::UnsetFlag();

View File

@@ -34,6 +34,6 @@ void Anchor::HandlePacket_UpdateBeansCount(nlohmann::json payload) {
return; return;
} }
AMMO(ITEM_BEAN) = payload["amount"].get<s8>(); AMMO(ITEM_BEAN) = payload.at("amount").get<s8>();
BEANS_BOUGHT = payload["amountBought"].get<s8>(); BEANS_BOUGHT = payload.at("amountBought").get<s8>();
} }

View File

@@ -54,7 +54,7 @@ void Anchor::SendPacket_UpdateClientState() {
} }
void Anchor::HandlePacket_UpdateClientState(nlohmann::json payload) { void Anchor::HandlePacket_UpdateClientState(nlohmann::json payload) {
uint32_t clientId = payload["clientId"].get<uint32_t>(); uint32_t clientId = payload.at("clientId").get<uint32_t>();
if (clients.contains(clientId)) { if (clients.contains(clientId)) {
AnchorClient client = payload["state"].get<AnchorClient>(); AnchorClient client = payload["state"].get<AnchorClient>();

View File

@@ -32,7 +32,7 @@ void Anchor::HandlePacket_UpdateDungeonItems(nlohmann::json payload) {
return; return;
} }
u16 mapIndex = payload["mapIndex"].get<u16>(); u16 mapIndex = payload.at("mapIndex").get<u16>();
gSaveContext.inventory.dungeonItems[mapIndex] = payload["dungeonItems"].get<u8>(); gSaveContext.inventory.dungeonItems[mapIndex] = payload.at("dungeonItems").get<u8>();
gSaveContext.inventory.dungeonKeys[mapIndex] = payload["dungeonKeys"].get<s8>(); gSaveContext.inventory.dungeonKeys[mapIndex] = payload.at("dungeonKeys").get<s8>();
} }

View File

@@ -2,8 +2,6 @@
#include "soh/Network/Anchor/JsonConversions.hpp" #include "soh/Network/Anchor/JsonConversions.hpp"
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <libultraship/libultraship.h> #include <libultraship/libultraship.h>
#include "soh/Enhancements/randomizer/entrance.h"
#include "soh/Enhancements/randomizer/dungeon.h"
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
#include "soh/Notification/Notification.h" #include "soh/Notification/Notification.h"
@@ -125,8 +123,9 @@ void Anchor::HandlePacket_UpdateTeamState(nlohmann::json payload) {
} }
isHandlingUpdateTeamState = true; 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 // This can happen in between file select and the game starting, so we can't use this check, but we need to ensure
// be careful to wrap PlayState usage in this check // we be careful to wrap PlayState usage in this check
//
// if (!IsSaveLoaded()) { // if (!IsSaveLoaded()) {
// return; // return;
// } // }
@@ -224,24 +223,24 @@ void Anchor::HandlePacket_UpdateTeamState(nlohmann::json payload) {
auto randoContext = Rando::Context::GetInstance(); auto randoContext = Rando::Context::GetInstance();
for (int i = 0; i < RC_MAX; i++) { for (int i = 0; i < RC_MAX; i++) {
auto itemLocation = payload["state"]["rando"].at("itemLocations").at(i);
// randoContext->GetItemLocation(i)->RefPlacedItem() = // randoContext->GetItemLocation(i)->RefPlacedItem() =
// payload["state"]["rando"]["itemLocations"][i]["rgID"].get<RandomizerGet>(); // itemLocation.at("rgID").get<RandomizerGet>();
OTRGlobals::Instance->gRandoContext->GetItemLocation(i)->SetCheckStatus( OTRGlobals::Instance->gRandoContext->GetItemLocation(i)->SetCheckStatus(
payload["state"]["rando"]["itemLocations"][i][0].get<RandomizerCheckStatus>()); itemLocation.at(0).get<RandomizerCheckStatus>());
OTRGlobals::Instance->gRandoContext->GetItemLocation(i)->SetIsSkipped( OTRGlobals::Instance->gRandoContext->GetItemLocation(i)->SetIsSkipped(itemLocation.at(1).get<u8>());
payload["state"]["rando"]["itemLocations"][i][1].get<u8>());
// if (payload["state"]["rando"]["itemLocations"][i].contains("fakeRgID")) { // if (itemLocation.contains("fakeRgID")) {
// randoContext->overrides.emplace(static_cast<RandomizerCheck>(i), // randoContext->overrides.emplace(static_cast<RandomizerCheck>(i),
// Rando::ItemOverride(static_cast<RandomizerCheck>(i), // Rando::ItemOverride(static_cast<RandomizerCheck>(i),
// payload["state"]["rando"]["itemLocations"][i]["fakeRgID"].get<RandomizerGet>())); // itemLocation.at("fakeRgID").get<RandomizerGet>()));
// randoContext->GetItemOverride(i).GetTrickName().english = // randoContext->GetItemOverride(i).GetTrickName().english =
// payload["state"]["rando"]["itemLocations"][i]["trickName"]["english"].get<std::string>(); // itemLocation.at("trickName").at("english").get<std::string>();
// randoContext->GetItemOverride(i).GetTrickName().french = // randoContext->GetItemOverride(i).GetTrickName().french =
// payload["state"]["rando"]["itemLocations"][i]["trickName"]["french"].get<std::string>(); // itemLocation.at("trickName").at("french").get<std::string>();
// } // }
// if (payload["state"]["rando"]["itemLocations"][i].contains("price")) { // if (itemLocation.contains("price")) {
// u16 price = payload["state"]["rando"]["itemLocations"][i]["price"].get<u16>(); // u16 price = itemLocation.at("price"].get<u16>();
// if (price > 0) { // if (price > 0) {
// randoContext->GetItemLocation(i)->SetCustomPrice(price); // randoContext->GetItemLocation(i)->SetCustomPrice(price);
// } // }