From c4b68976359a9be429cc5c194ee672feb7b67d0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Sun, 19 Apr 2020 22:35:24 +0200 Subject: [PATCH] Address possible nullptr dereferences --- src/openrct2-ui/windows/RideConstruction.cpp | 3 ++- src/openrct2-ui/windows/TopToolbar.cpp | 14 ++++++++------ src/openrct2/ride/TrackDesignSave.cpp | 12 ++++++++++++ src/openrct2/windows/_legacy.cpp | 6 +++--- src/openrct2/world/Map.cpp | 7 ++++++- 5 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/openrct2-ui/windows/RideConstruction.cpp b/src/openrct2-ui/windows/RideConstruction.cpp index 745726c9ef..8fc121ec55 100644 --- a/src/openrct2-ui/windows/RideConstruction.cpp +++ b/src/openrct2-ui/windows/RideConstruction.cpp @@ -1844,7 +1844,8 @@ static void window_ride_construction_construct(rct_window* w) _currentTrackSelectionFlags |= TRACK_SELECTION_FLAG_TRACK_PLACE_ACTION_QUEUED; } - if (dynamic_cast(res.get())->GroundFlags & TRACK_ELEMENT_LOCATION_IS_UNDERGROUND) + auto tpar = dynamic_cast(res.get()); + if (tpar != nullptr && tpar->GroundFlags & TRACK_ELEMENT_LOCATION_IS_UNDERGROUND) { viewport_set_visibility(1); } diff --git a/src/openrct2-ui/windows/TopToolbar.cpp b/src/openrct2-ui/windows/TopToolbar.cpp index d6c3d957ed..0de292c018 100644 --- a/src/openrct2-ui/windows/TopToolbar.cpp +++ b/src/openrct2-ui/windows/TopToolbar.cpp @@ -2559,17 +2559,18 @@ static money32 try_place_ghost_scenery( { map_tile.x, map_tile.y, gSceneryPlaceZ, rotation }, quadrant, entryIndex, primaryColour, secondaryColour); smallSceneryPlaceAction.SetFlags(GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED); auto res = GameActions::Execute(&smallSceneryPlaceAction); - if (res->Error != GA_ERROR::OK) + auto sspar = dynamic_cast(res.get()); + if (sspar == nullptr || res->Error != GA_ERROR::OK) return MONEY32_UNDEFINED; gSceneryPlaceRotation = static_cast(parameter_3 & 0xFF); gSceneryPlaceObject.SceneryType = SCENERY_TYPE_SMALL; gSceneryPlaceObject.EntryIndex = entryIndex; - tileElement = dynamic_cast(res.get())->tileElement; + tileElement = sspar->tileElement; gSceneryGhostPosition = { map_tile, tileElement->GetBaseZ() }; gSceneryQuadrant = tileElement->AsSmallScenery()->GetSceneryQuadrant(); - if (dynamic_cast(res.get())->GroundFlags & ELEMENT_IS_UNDERGROUND) + if (sspar->GroundFlags & ELEMENT_IS_UNDERGROUND) { // Set underground on viewport_set_visibility(4); @@ -2646,15 +2647,16 @@ static money32 try_place_ghost_scenery( sceneryPlaceAction.SetFlags( GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND); auto res = GameActions::Execute(&sceneryPlaceAction); - if (res->Error != GA_ERROR::OK) + auto lspar = dynamic_cast(res.get()); + if (lspar == nullptr || res->Error != GA_ERROR::OK) return MONEY32_UNDEFINED; gSceneryPlaceRotation = loc.direction; - tileElement = dynamic_cast(res.get())->tileElement; + tileElement = lspar->tileElement; gSceneryGhostPosition = { map_tile, tileElement->GetBaseZ() }; - if (dynamic_cast(res.get())->GroundFlags & ELEMENT_IS_UNDERGROUND) + if (lspar->GroundFlags & ELEMENT_IS_UNDERGROUND) { // Set underground on viewport_set_visibility(4); diff --git a/src/openrct2/ride/TrackDesignSave.cpp b/src/openrct2/ride/TrackDesignSave.cpp index bd3e0e6aaf..f2ca81eb43 100644 --- a/src/openrct2/ride/TrackDesignSave.cpp +++ b/src/openrct2/ride/TrackDesignSave.cpp @@ -227,6 +227,12 @@ static void track_design_save_add_large_scenery(const CoordsXY& loc, LargeScener rct_large_scenery_tile *sceneryTiles, *tile; int32_t direction, sequence; + if (tileElement == nullptr) + { + log_warning("Null tile element"); + return; + } + int32_t entryType = tileElement->GetEntryIndex(); auto entry = object_entry_get_entry(OBJECT_TYPE_LARGE_SCENERY, entryType); sceneryTiles = get_large_scenery_entry(entryType)->large_scenery.tiles; @@ -404,6 +410,12 @@ static void track_design_save_remove_large_scenery(const CoordsXY& loc, LargeSce rct_large_scenery_tile *sceneryTiles, *tile; int32_t direction, sequence; + if (tileElement == nullptr) + { + log_warning("Null tile element"); + return; + } + int32_t entryType = tileElement->GetEntryIndex(); auto entry = object_entry_get_entry(OBJECT_TYPE_LARGE_SCENERY, entryType); sceneryTiles = get_large_scenery_entry(entryType)->large_scenery.tiles; diff --git a/src/openrct2/windows/_legacy.cpp b/src/openrct2/windows/_legacy.cpp index 7d30b46009..8057474e17 100644 --- a/src/openrct2/windows/_legacy.cpp +++ b/src/openrct2/windows/_legacy.cpp @@ -87,7 +87,8 @@ money32 place_provisional_track_piece( trackPlaceAction.SetFlags(GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND | GAME_COMMAND_FLAG_GHOST); // This command must not be sent over the network auto res = GameActions::Execute(&trackPlaceAction); - result = res->Error == GA_ERROR::OK ? res->Cost : MONEY32_UNDEFINED; + auto tpar = dynamic_cast(res.get()); + result = ((tpar == nullptr) || (res->Error == GA_ERROR::OK)) ? res->Cost : MONEY32_UNDEFINED; if (result == MONEY32_UNDEFINED) return result; @@ -110,8 +111,7 @@ money32 place_provisional_track_piece( _unkF440C5.z = z; _unkF440C5.direction = trackDirection; _currentTrackSelectionFlags |= TRACK_SELECTION_FLAG_TRACK; - viewport_set_visibility( - (dynamic_cast(res.get())->GroundFlags & TRACK_ELEMENT_LOCATION_IS_UNDERGROUND) ? 1 : 3); + viewport_set_visibility((tpar->GroundFlags & TRACK_ELEMENT_LOCATION_IS_UNDERGROUND) ? 1 : 3); if (_currentTrackSlopeEnd != 0) viewport_set_visibility(2); diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index e3dbddfc59..d3bc27371d 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -1480,7 +1480,12 @@ bool map_can_construct_with_clear_at( { *price += res->Cost; } - gMapGroundFlags = dynamic_cast(res.get())->GroundFlags; + auto ccr = dynamic_cast(res.get()); + if (ccr == nullptr) + { + return false; + } + gMapGroundFlags = ccr->GroundFlags; return res->Error == GA_ERROR::OK; }