From 699d84b70c18e6152ce6a9d0afeb5537c2e45b13 Mon Sep 17 00:00:00 2001 From: Chase Cooper Date: Sat, 7 Mar 2026 23:27:09 -0500 Subject: [PATCH] Add safety checks and fix a issue with vector going OOR --- Minecraft.Client/Common/UI/UILayer.cpp | 6 +++--- Minecraft.Client/EntityRenderDispatcher.cpp | 5 +++++ Minecraft.Client/GameRenderer.cpp | 5 +++++ Minecraft.Client/Gui.cpp | 8 +++++++- Minecraft.Client/ItemInHandRenderer.cpp | 5 +++++ Minecraft.Client/LevelRenderer.cpp | 18 ++++++++++++++++++ Minecraft.Client/LivingEntityRenderer.cpp | 10 ++++++++++ Minecraft.Client/MobRenderer.cpp | 10 ++++++++++ .../PSVita/Network/SonyVoiceChat_Vita.cpp | 2 +- Minecraft.Client/ParticleEngine.cpp | 5 +++++ Minecraft.Client/PlayerRenderer.cpp | 6 ++++++ Minecraft.World/AbstractContainerMenu.cpp | 14 +++++++++++++- Minecraft.World/EnchantmentMenu.cpp | 11 ++++++++++- Minecraft.World/MerchantRecipeList.cpp | 11 ++++++++++- Minecraft.World/ServersideAttributeMap.cpp | 4 ++++ 15 files changed, 112 insertions(+), 8 deletions(-) diff --git a/Minecraft.Client/Common/UI/UILayer.cpp b/Minecraft.Client/Common/UI/UILayer.cpp index bf360c07f..e1c388f54 100644 --- a/Minecraft.Client/Common/UI/UILayer.cpp +++ b/Minecraft.Client/Common/UI/UILayer.cpp @@ -102,7 +102,7 @@ void UILayer::render(S32 width, S32 height, C4JRender::eViewportType viewport) bool UILayer::IsSceneInStack(EUIScene scene) { bool inStack = false; - for(size_t i = (int)m_sceneStack.size() - 1;i >= 0; --i) + for(int i = static_cast(m_sceneStack.size()) - 1; i >= 0; --i) { if(m_sceneStack[i]->getSceneType() == scene) { @@ -118,7 +118,7 @@ bool UILayer::HasFocus(int iPad) bool hasFocus = false; if(m_hasFocus) { - for(size_t i = (int)m_sceneStack.size() - 1;i >= 0; --i) + for(int i = (int)m_sceneStack.size() - 1; i >= 0; --i) { if(m_sceneStack[i]->stealsFocus() ) { @@ -146,7 +146,7 @@ bool UILayer::hidesLowerScenes() } if(!hidesScenes && !m_sceneStack.empty()) { - for(size_t i = (int)m_sceneStack.size() - 1;i >= 0; --i) + for(int i = static_cast(m_sceneStack.size()) - 1; i >= 0; --i) { if(m_sceneStack[i]->hidesLowerScenes()) { diff --git a/Minecraft.Client/EntityRenderDispatcher.cpp b/Minecraft.Client/EntityRenderDispatcher.cpp index cc14558f9..b54967bde 100644 --- a/Minecraft.Client/EntityRenderDispatcher.cpp +++ b/Minecraft.Client/EntityRenderDispatcher.cpp @@ -244,6 +244,11 @@ void EntityRenderDispatcher::prepare(Level *level, Textures *textures, Font *fon void EntityRenderDispatcher::render(shared_ptr entity, float a) { + if (entity == nullptr) + { + return; + } + double x = entity->xOld + (entity->x - entity->xOld) * a; double y = entity->yOld + (entity->y - entity->yOld) * a; double z = entity->zOld + (entity->z - entity->zOld) * a; diff --git a/Minecraft.Client/GameRenderer.cpp b/Minecraft.Client/GameRenderer.cpp index ecd2f462b..9fe3e26ba 100644 --- a/Minecraft.Client/GameRenderer.cpp +++ b/Minecraft.Client/GameRenderer.cpp @@ -1133,6 +1133,11 @@ int GameRenderer::getLightTexture(int iPad, Level *level) void GameRenderer::render(float a, bool bFirst) { + if (mc->player == nullptr) + { + return; + } + if( _updateLightTexture && bFirst) updateLightTexture(a); if (Display::isActive()) { diff --git a/Minecraft.Client/Gui.cpp b/Minecraft.Client/Gui.cpp index 6217bc40c..8ca65dfed 100644 --- a/Minecraft.Client/Gui.cpp +++ b/Minecraft.Client/Gui.cpp @@ -63,6 +63,12 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse) // 4J Stu - I have copied this code for XUI_BaseScene. If/when it gets changed it should be broken out // 4J - altered to force full screen mode to 3X scaling, and any split screen modes to 2X scaling. This is so that the further scaling by 0.5 that // happens in split screen modes results in a final scaling of 1 rather than 1.5. + + if (minecraft->player == nullptr) + { + return; + } + int splitYOffset;// = 20; // This offset is applied when doing the 2X scaling above to move the gui out of the way of the tool tips int guiScale;// = ( minecraft->player->m_iScreenSection == C4JRender::VIEWPORT_TYPE_FULLSCREEN ? 3 : 2 ); int iPad=minecraft->player->GetXboxPad(); @@ -845,7 +851,7 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse) #ifndef _FINAL_BUILD MemSect(31); - if (minecraft->options->renderDebug) + if (minecraft->options->renderDebug && minecraft->player != nullptr && minecraft->level != nullptr) { const int debugLeft = 1; const int debugTop = 1; diff --git a/Minecraft.Client/ItemInHandRenderer.cpp b/Minecraft.Client/ItemInHandRenderer.cpp index 4cebda2fd..152a56688 100644 --- a/Minecraft.Client/ItemInHandRenderer.cpp +++ b/Minecraft.Client/ItemInHandRenderer.cpp @@ -373,6 +373,11 @@ void ItemInHandRenderer::render(float a) float h = oHeight + (height - oHeight) * a; shared_ptr player = minecraft->player; + if (player == nullptr) + { + return; + } + // 4J - added so we can adjust the position of the hands for horizontal & vertical split screens float fudgeX = 0.0f; float fudgeY = 0.0f; diff --git a/Minecraft.Client/LevelRenderer.cpp b/Minecraft.Client/LevelRenderer.cpp index 8d61e1b2d..82fc3e9bc 100644 --- a/Minecraft.Client/LevelRenderer.cpp +++ b/Minecraft.Client/LevelRenderer.cpp @@ -507,6 +507,11 @@ void LevelRenderer::allChanged(int playerIndex) void LevelRenderer::renderEntities(Vec3 *cam, Culler *culler, float a) { + if (mc == nullptr || mc->player == nullptr) + { + return; + } + int playerIndex = mc->player->GetXboxPad(); // 4J added // 4J Stu - Set these up every time, even when not rendering as other things (like particle render) may depend on it for those frames. @@ -524,6 +529,10 @@ void LevelRenderer::renderEntities(Vec3 *cam, Culler *culler, float a) culledEntities = 0; shared_ptr player = mc->cameraTargetPlayer; + if (player == nullptr) + { + return; + } EntityRenderDispatcher::xOff = (player->xOld + (player->x - player->xOld) * a); EntityRenderDispatcher::yOff = (player->yOld + (player->y - player->yOld) * a); @@ -758,12 +767,21 @@ int compare (const void * a, const void * b) int LevelRenderer::renderChunks(int from, int to, int layer, double alpha) { + if (mc == nullptr || mc->player == nullptr) + { + return 0; + } + int playerIndex = mc->player->GetXboxPad(); // 4J added #if 1 // 4J - cut down version, we're not using offsetted render lists, or a sorted chunk list, anymore mc->gameRenderer->turnOnLightLayer(alpha); // 4J - brought forward from 1.8.2 shared_ptr player = mc->cameraTargetPlayer; + if (player == nullptr) + { + return 0; + } double xOff = player->xOld + (player->x - player->xOld) * alpha; double yOff = player->yOld + (player->y - player->yOld) * alpha; double zOff = player->zOld + (player->z - player->zOld) * alpha; diff --git a/Minecraft.Client/LivingEntityRenderer.cpp b/Minecraft.Client/LivingEntityRenderer.cpp index 600a66554..b3478ba92 100644 --- a/Minecraft.Client/LivingEntityRenderer.cpp +++ b/Minecraft.Client/LivingEntityRenderer.cpp @@ -37,8 +37,18 @@ float LivingEntityRenderer::rotlerp(float from, float to, float a) void LivingEntityRenderer::render(shared_ptr _mob, double x, double y, double z, float rot, float a) { + if (_mob == nullptr) + { + return; + } + shared_ptr mob = dynamic_pointer_cast(_mob); + if (mob == nullptr) + { + return; + } + glPushMatrix(); glDisable(GL_CULL_FACE); diff --git a/Minecraft.Client/MobRenderer.cpp b/Minecraft.Client/MobRenderer.cpp index 92c89394a..539980702 100644 --- a/Minecraft.Client/MobRenderer.cpp +++ b/Minecraft.Client/MobRenderer.cpp @@ -15,8 +15,18 @@ MobRenderer::MobRenderer(Model *model, float shadow) : LivingEntityRenderer(mode void MobRenderer::render(shared_ptr _mob, double x, double y, double z, float rot, float a) { + if (_mob == nullptr) + { + return; + } + shared_ptr mob = dynamic_pointer_cast(_mob); + if (mob == nullptr) + { + return; + } + LivingEntityRenderer::render(mob, x, y, z, rot, a); renderLeash(mob, x, y, z, rot, a); } diff --git a/Minecraft.Client/PSVita/Network/SonyVoiceChat_Vita.cpp b/Minecraft.Client/PSVita/Network/SonyVoiceChat_Vita.cpp index cf1ce9ad5..37fea8282 100644 --- a/Minecraft.Client/PSVita/Network/SonyVoiceChat_Vita.cpp +++ b/Minecraft.Client/PSVita/Network/SonyVoiceChat_Vita.cpp @@ -668,7 +668,7 @@ void SonyVoiceChat_Vita::tick() EnterCriticalSection(&m_csRemoteConnections); - for(size_t i=m_remoteConnections.size()-1;i>=0;i--) + for(int i = (int)m_remoteConnections.size() - 1; i >= 0; i--) { if(m_remoteConnections[i]->m_bFlaggedForShutdown) { diff --git a/Minecraft.Client/ParticleEngine.cpp b/Minecraft.Client/ParticleEngine.cpp index efc09c9ad..f8a8ec230 100644 --- a/Minecraft.Client/ParticleEngine.cpp +++ b/Minecraft.Client/ParticleEngine.cpp @@ -83,6 +83,11 @@ void ParticleEngine::tick() void ParticleEngine::render(shared_ptr player, float a, int list) { + if (player == nullptr) + { + return; + } + // 4J - change brought forward from 1.2.3 float xa = Camera::xa; float za = Camera::za; diff --git a/Minecraft.Client/PlayerRenderer.cpp b/Minecraft.Client/PlayerRenderer.cpp index 68dae2eeb..a9b945440 100644 --- a/Minecraft.Client/PlayerRenderer.cpp +++ b/Minecraft.Client/PlayerRenderer.cpp @@ -153,9 +153,15 @@ void PlayerRenderer::prepareSecondPassArmor(shared_ptr _player, in void PlayerRenderer::render(shared_ptr _mob, double x, double y, double z, float rot, float a) { + if (_mob == nullptr) + { + return; + } + // 4J - dynamic cast required because we aren't using templates/generics in our version shared_ptr mob = dynamic_pointer_cast(_mob); + if(mob == nullptr) return; if(mob->hasInvisiblePrivilege()) return; shared_ptr item = mob->inventory->getSelected(); diff --git a/Minecraft.World/AbstractContainerMenu.cpp b/Minecraft.World/AbstractContainerMenu.cpp index 1fd400e56..10d8afdcc 100644 --- a/Minecraft.World/AbstractContainerMenu.cpp +++ b/Minecraft.World/AbstractContainerMenu.cpp @@ -131,11 +131,19 @@ Slot *AbstractContainerMenu::getSlotFor(shared_ptr c, int index) Slot *AbstractContainerMenu::getSlot(int index) { + if (index < 0 || index >= static_cast(slots.size())) + { + return nullptr; + } return slots.at(index); } shared_ptr AbstractContainerMenu::quickMoveStack(shared_ptr player, int slotIndex) { + if (slotIndex < 0 || slotIndex >= static_cast(slots.size())) + { + return nullptr; + } Slot *slot = slots.at(slotIndex); if (slot != nullptr) { @@ -251,7 +259,7 @@ shared_ptr AbstractContainerMenu::clicked(int slotIndex, int butto } else if (clickType == CLICK_QUICK_MOVE) { - if (slotIndex < 0) return nullptr; + if (slotIndex < 0 || slotIndex >= static_cast(slots.size())) return nullptr; Slot *slot = slots.at(slotIndex); if(slot != nullptr && slot->mayPickup(player)) { @@ -408,6 +416,7 @@ shared_ptr AbstractContainerMenu::clicked(int slotIndex, int butto } else if (clickType == CLICK_SWAP && buttonNum >= 0 && buttonNum < 9) { + if (slotIndex < 0 || slotIndex >= static_cast(slots.size())) return nullptr; Slot *slot = slots.at(slotIndex); if (slot->mayPickup(player)) { @@ -449,6 +458,7 @@ shared_ptr AbstractContainerMenu::clicked(int slotIndex, int butto } else if (clickType == CLICK_CLONE && player->abilities.instabuild && inventory->getCarried() == nullptr && slotIndex >= 0) { + if (slotIndex >= static_cast(slots.size())) return nullptr; Slot *slot = slots.at(slotIndex); if (slot != nullptr && slot->hasItem()) { @@ -459,6 +469,7 @@ shared_ptr AbstractContainerMenu::clicked(int slotIndex, int butto } else if (clickType == CLICK_THROW && inventory->getCarried() == nullptr && slotIndex >= 0) { + if (slotIndex >= static_cast(slots.size())) return nullptr; Slot *slot = slots.at(slotIndex); if (slot != nullptr && slot->hasItem() && slot->mayPickup(player)) { @@ -469,6 +480,7 @@ shared_ptr AbstractContainerMenu::clicked(int slotIndex, int butto } else if (clickType == CLICK_PICKUP_ALL && slotIndex >= 0) { + if (slotIndex >= static_cast(slots.size())) return nullptr; Slot *slot = slots.at(slotIndex); shared_ptr carried = inventory->getCarried(); diff --git a/Minecraft.World/EnchantmentMenu.cpp b/Minecraft.World/EnchantmentMenu.cpp index f37f336ea..6af7113ac 100644 --- a/Minecraft.World/EnchantmentMenu.cpp +++ b/Minecraft.World/EnchantmentMenu.cpp @@ -215,9 +215,18 @@ bool EnchantmentMenu::stillValid(shared_ptr player) shared_ptr EnchantmentMenu::quickMoveStack(shared_ptr player, int slotIndex) { + if (slotIndex < 0 || slotIndex >= static_cast(slots.size())) + { + return nullptr; + } + shared_ptr clicked = nullptr; Slot *slot = slots.at(slotIndex); - Slot *IngredientSlot = slots.at(INGREDIENT_SLOT); + Slot *IngredientSlot = nullptr; + if (INGREDIENT_SLOT >= 0 && INGREDIENT_SLOT < static_cast(slots.size())) + { + IngredientSlot = slots.at(INGREDIENT_SLOT); + } if (slot != nullptr && slot->hasItem()) { diff --git a/Minecraft.World/MerchantRecipeList.cpp b/Minecraft.World/MerchantRecipeList.cpp index 4e1684d45..b1498389b 100644 --- a/Minecraft.World/MerchantRecipeList.cpp +++ b/Minecraft.World/MerchantRecipeList.cpp @@ -21,7 +21,12 @@ MerchantRecipeList::~MerchantRecipeList() MerchantRecipe *MerchantRecipeList::getRecipeFor(shared_ptr buyA, shared_ptr buyB, int selectionHint) { - if (selectionHint > 0 && selectionHint < m_recipes.size()) + if (buyA == nullptr) + { + return nullptr; + } + + if (selectionHint > 0 && selectionHint < static_cast(m_recipes.size())) { // attempt to match vs the hint MerchantRecipe *r = m_recipes.at(selectionHint); @@ -166,6 +171,10 @@ void MerchantRecipeList::push_back(MerchantRecipe *recipe) MerchantRecipe *MerchantRecipeList::at(size_t index) { + if (index >= m_recipes.size()) + { + return nullptr; + } return m_recipes.at(index); } diff --git a/Minecraft.World/ServersideAttributeMap.cpp b/Minecraft.World/ServersideAttributeMap.cpp index 07544e766..c73086662 100644 --- a/Minecraft.World/ServersideAttributeMap.cpp +++ b/Minecraft.World/ServersideAttributeMap.cpp @@ -72,6 +72,10 @@ unordered_set *ServersideAttributeMap::getSyncableAttribute for (size_t i = 0; i < atts.size(); i++) { AttributeInstance *instance = atts.at(i); + if (instance == nullptr) + { + continue; + } if (instance->getAttribute()->isClientSyncable()) {