From 35577f5b19318f57b83b57e1cd08f1f350c8e677 Mon Sep 17 00:00:00 2001 From: Tulio Leao Date: Sun, 13 Oct 2019 09:24:19 -0300 Subject: [PATCH] Avoid dereferencing invalid map_get_first_element_at return --- src/openrct2-ui/interface/ViewportInteraction.cpp | 2 ++ src/openrct2-ui/windows/Banner.cpp | 4 ++++ src/openrct2-ui/windows/Footpath.cpp | 2 ++ src/openrct2-ui/windows/Sign.cpp | 8 ++++++++ src/openrct2-ui/windows/TileInspector.cpp | 4 ++++ src/openrct2/actions/ClearAction.hpp | 4 ++++ src/openrct2/actions/FootpathPlaceAction.hpp | 2 ++ src/openrct2/actions/LandSetHeightAction.hpp | 10 ++++++++++ src/openrct2/ride/TrackDesign.cpp | 11 ++++------- src/openrct2/world/MapAnimation.cpp | 2 ++ 10 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/openrct2-ui/interface/ViewportInteraction.cpp b/src/openrct2-ui/interface/ViewportInteraction.cpp index 79b1f07029..0d3633b113 100644 --- a/src/openrct2-ui/interface/ViewportInteraction.cpp +++ b/src/openrct2-ui/interface/ViewportInteraction.cpp @@ -528,6 +528,8 @@ static void viewport_interaction_remove_footpath(TileElement* tileElement, int32 footpath_provisional_update(); tileElement2 = map_get_first_element_at(x / 32, y / 32); + if (tileElement2 == nullptr) + return; do { if (tileElement2->GetType() == TILE_ELEMENT_TYPE_PATH && tileElement2->base_height == z) diff --git a/src/openrct2-ui/windows/Banner.cpp b/src/openrct2-ui/windows/Banner.cpp index 53c862ceac..07044a6261 100644 --- a/src/openrct2-ui/windows/Banner.cpp +++ b/src/openrct2-ui/windows/Banner.cpp @@ -137,6 +137,8 @@ rct_window* window_banner_open(rct_windownumber number) int32_t view_y = banner->position.y << 5; TileElement* tile_element = map_get_first_element_at(view_x / 32, view_y / 32); + if (tile_element == nullptr) + return nullptr; while (1) { if ((tile_element->GetType() == TILE_ELEMENT_TYPE_BANNER) && (tile_element->AsBanner()->GetIndex() == w->number)) @@ -176,6 +178,8 @@ static void window_banner_mouseup(rct_window* w, rct_widgetindex widgetIndex) int32_t y = banner->position.y << 5; TileElement* tile_element = map_get_first_element_at(x / 32, y / 32); + if (tile_element == nullptr) + return; while (1) { diff --git a/src/openrct2-ui/windows/Footpath.cpp b/src/openrct2-ui/windows/Footpath.cpp index 04e4818655..8404963a69 100644 --- a/src/openrct2-ui/windows/Footpath.cpp +++ b/src/openrct2-ui/windows/Footpath.cpp @@ -1094,6 +1094,8 @@ static TileElement* footpath_get_tile_element_to_remove() tileElement = map_get_first_element_at(x, y); do { + if (tileElement == nullptr) + break; if (tileElement->GetType() == TILE_ELEMENT_TYPE_PATH) { if (tileElement->base_height == z) diff --git a/src/openrct2-ui/windows/Sign.cpp b/src/openrct2-ui/windows/Sign.cpp index 22cbbb8272..6eb04610c6 100644 --- a/src/openrct2-ui/windows/Sign.cpp +++ b/src/openrct2-ui/windows/Sign.cpp @@ -160,6 +160,8 @@ rct_window* window_sign_open(rct_windownumber number) int32_t view_y = banner->position.y << 5; TileElement* tile_element = map_get_first_element_at(view_x / 32, view_y / 32); + if (tile_element == nullptr) + return nullptr; while (1) { @@ -216,6 +218,8 @@ static void window_sign_mouseup(rct_window* w, rct_widgetindex widgetIndex) int32_t x = banner->position.x << 5; int32_t y = banner->position.y << 5; auto tile_element = map_get_first_element_at(x / 32, y / 32); + if (tile_element == nullptr) + return; while (1) { if (tile_element->GetType() == TILE_ELEMENT_TYPE_LARGE_SCENERY) @@ -405,6 +409,8 @@ rct_window* window_sign_small_open(rct_windownumber number) int32_t view_y = banner->position.y << 5; TileElement* tile_element = map_get_first_element_at(view_x / 32, view_y / 32); + if (tile_element == nullptr) + return nullptr; while (1) { @@ -460,6 +466,8 @@ static void window_sign_small_mouseup(rct_window* w, rct_widgetindex widgetIndex int32_t x = banner->position.x << 5; int32_t y = banner->position.y << 5; auto tile_element = map_get_first_element_at(x / 32, y / 32); + if (tile_element == nullptr) + return; while (true) { if (tile_element->GetType() == TILE_ELEMENT_TYPE_WALL) diff --git a/src/openrct2-ui/windows/TileInspector.cpp b/src/openrct2-ui/windows/TileInspector.cpp index 9af60dfe70..b77d4ffffc 100644 --- a/src/openrct2-ui/windows/TileInspector.cpp +++ b/src/openrct2-ui/windows/TileInspector.cpp @@ -603,6 +603,8 @@ static void window_tile_inspector_load_tile(rct_window* w, TileElement* elementT int16_t numItems = 0; do { + if (element == nullptr) + break; if (element == elementToSelect) { windowTileInspectorSelectedIndex = numItems; @@ -2170,6 +2172,8 @@ static void window_tile_inspector_scrollpaint(rct_window* w, rct_drawpixelinfo* gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM; do { + if (tileElement == nullptr) + break; const bool selectedRow = i == windowTileInspectorSelectedIndex; const bool hoveredRow = i == windowTileInspectorHighlightedIndex; int32_t type = tileElement->GetType(); diff --git a/src/openrct2/actions/ClearAction.hpp b/src/openrct2/actions/ClearAction.hpp index 419b784086..8ff04526ab 100644 --- a/src/openrct2/actions/ClearAction.hpp +++ b/src/openrct2/actions/ClearAction.hpp @@ -144,6 +144,8 @@ private: { tileEdited = false; tileElement = map_get_first_element_at(x, y); + if (tileElement == nullptr) + return totalCost; do { auto type = tileElement->GetType(); @@ -241,6 +243,8 @@ private: auto tileElement = map_get_first_element_at(x, y); do { + if (tileElement == nullptr) + break; if (tileElement->GetType() == TILE_ELEMENT_TYPE_LARGE_SCENERY) { tileElement->AsLargeScenery()->SetIsAccounted(false); diff --git a/src/openrct2/actions/FootpathPlaceAction.hpp b/src/openrct2/actions/FootpathPlaceAction.hpp index ec765b0277..8e2067f876 100644 --- a/src/openrct2/actions/FootpathPlaceAction.hpp +++ b/src/openrct2/actions/FootpathPlaceAction.hpp @@ -440,6 +440,8 @@ private: tileElement = map_get_first_element_at(x, y); do { + if (tileElement == nullptr) + break; if (tileElement->GetType() == TILE_ELEMENT_TYPE_PATH && tileElement->base_height == z && (tileElement->AsPath()->IsSloped() == isSloped) && (tileElement->AsPath()->GetSlopeDirection() == (slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK))) diff --git a/src/openrct2/actions/LandSetHeightAction.hpp b/src/openrct2/actions/LandSetHeightAction.hpp index e6f329542b..856190016d 100644 --- a/src/openrct2/actions/LandSetHeightAction.hpp +++ b/src/openrct2/actions/LandSetHeightAction.hpp @@ -201,6 +201,8 @@ private: TileElement* tileElement = map_get_first_element_at(_coords.x / 32, _coords.y / 32); do { + if (tileElement == nullptr) + break; if (tileElement->GetType() != TILE_ELEMENT_TYPE_SMALL_SCENERY) continue; if (_height > tileElement->clearance_height) @@ -222,6 +224,8 @@ private: TileElement* tileElement = map_get_first_element_at(_coords.x / 32, _coords.y / 32); do { + if (tileElement == nullptr) + break; if (tileElement->GetType() != TILE_ELEMENT_TYPE_SMALL_SCENERY) continue; if (_height > tileElement->clearance_height) @@ -239,6 +243,8 @@ private: TileElement* tileElement = map_get_first_element_at(_coords.x / 32, _coords.y / 32); do { + if (tileElement == nullptr) + break; if (tileElement->GetType() != TILE_ELEMENT_TYPE_SMALL_SCENERY) continue; if (_height > tileElement->clearance_height) @@ -254,6 +260,8 @@ private: TileElement* tileElement = map_get_first_element_at(_coords.x / 32, _coords.y / 32); do { + if (tileElement == nullptr) + break; if (tileElement->GetType() == TILE_ELEMENT_TYPE_TRACK) { ride_id_t rideIndex = tileElement->AsTrack()->GetRideIndex(); @@ -309,6 +317,8 @@ private: TileElement* tileElement = map_get_first_element_at(_coords.x / 32, _coords.y / 32); do { + if (tileElement == nullptr) + break; int32_t elementType = tileElement->GetType(); // Wall's and Small Scenery are removed and therefore do not need checked diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index aeb3033198..b54c58d803 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -280,20 +280,17 @@ rct_string_id TrackDesign::CreateTrackDesignTrack(const Ride& ride) int16_t y = location.y * 32; TileElement* tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + continue; + do { - if (tileElement == nullptr) - break; if (tileElement->GetType() != TILE_ELEMENT_TYPE_ENTRANCE) continue; if (tileElement->base_height == z) break; } while (!(tileElement++)->IsLastForTile()); - if (tileElement == nullptr) - { - continue; - } // Add something that stops this from walking off the end Direction entranceDirection = tileElement->GetDirection(); @@ -402,7 +399,7 @@ rct_string_id TrackDesign::CreateTrackDesignMaze(const Ride& ride) do { if (tileElement == nullptr) - break; + return STR_TRACK_TOO_LARGE_OR_TOO_MUCH_SCENERY; if (tileElement->GetType() != TILE_ELEMENT_TYPE_ENTRANCE) continue; if (tileElement->AsEntrance()->GetEntranceType() != ENTRANCE_TYPE_RIDE_ENTRANCE) diff --git a/src/openrct2/world/MapAnimation.cpp b/src/openrct2/world/MapAnimation.cpp index f05a9b4e9d..5f3b1f7176 100644 --- a/src/openrct2/world/MapAnimation.cpp +++ b/src/openrct2/world/MapAnimation.cpp @@ -365,6 +365,8 @@ static bool map_animation_invalidate_track_whirlpool(int32_t x, int32_t y, int32 TileElement* tileElement; tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return true; do { if (tileElement->base_height != baseZ)