From b793d7e79aefa8758cad298f16ccc8d2232667dc Mon Sep 17 00:00:00 2001 From: Tulio Leao Date: Wed, 9 Oct 2019 11:02:21 -0300 Subject: [PATCH] Avoid dereferencing map_get_first_element_at nullptr on libopenrct2 (#10013) * Avoid dereferencing map_get_first_element_at nullptr on Map.cpp * Avoid dereferencing map_get_first_element_at nullptr on MapAnimation.cpp Returning true or internal control variable, based on what was seen on `map_animation_invalidate_track_onridephoto` * Avoid dereferencing map_get_first_element_at nullptr on Park.cpp * Avoid dereferencing map_get_first_element_at nullptr on Scenery.cpp * Avoid dereferencing map_get_first_element_at nullptr on Sprite.cpp * Avoid dereferencing map_get_first_element_at nullptr on TileInspector.cpp * Avoid dereferencing map_get_first_element_at nullptr on Wall.cpp * Avoid dereferencing map_get_first_element_at nullptr on Fountain.cpp * Avoid dereferencing map_get_first_element_at nullptr on Footpath.cpp * Avoid dereferencing map_get_first_element_at nullptr on Entrance.cpp * Avoid dereferencing map_get_first_element_at nullptr on Banner.cpp * Avoid dereferencing map_get_first_element_at nullptr on Vehicle.cpp * Avoid dereferencing map_get_first_element_at nullptr on TrackDesignSave.cpp * Avoid dereferencing map_get_first_element_at nullptr on TrackDesign.cpp * Avoid dereferencing map_get_first_element_at nullptr on Track.cpp * Avoid dereferencing map_get_first_element_at nullptr on Station.cpp * Avoid dereferencing map_get_first_element_at nullptr on RideRatings.cpp * Avoid dereferencing map_get_first_element_at nullptr on Ride.cpp * Avoid dereferencing map_get_first_element_at nullptr on S4Importer.cpp * Avoid dereferencing map_get_first_element_at nullptr on Staff.cpp * Avoid dereferencing map_get_first_element_at nullptr on Peep.cpp * Avoid dereferencing map_get_first_element_at nullptr on GuestPathfinding.cpp * Avoid dereferencing map_get_first_element_at nullptr on Guest.cpp * Avoid dereferencing map_get_first_element_at nullptr on VirtualFloor.cpp * Avoid dereferencing map_get_first_element_at nullptr on Paint.TileElement.cpp * Fix issues raised on review * Fix remaining review issues. * Early exit on loops if tileElement is nullptr * Fix clang-format issues --- src/openrct2/paint/VirtualFloor.cpp | 2 ++ .../paint/tile_element/Paint.TileElement.cpp | 2 ++ src/openrct2/peep/Guest.cpp | 23 +++++++++++++++- src/openrct2/peep/GuestPathfinding.cpp | 6 +++++ src/openrct2/peep/Peep.cpp | 6 +++++ src/openrct2/peep/Staff.cpp | 11 +++++++- src/openrct2/rct1/S4Importer.cpp | 4 +++ src/openrct2/ride/Ride.cpp | 18 +++++++++++++ src/openrct2/ride/RideRatings.cpp | 18 +++++++++++++ src/openrct2/ride/Station.cpp | 4 +++ src/openrct2/ride/Track.cpp | 2 ++ src/openrct2/ride/TrackDesign.cpp | 2 ++ src/openrct2/ride/TrackDesignSave.cpp | 2 ++ src/openrct2/ride/Vehicle.cpp | 4 +++ src/openrct2/world/Banner.cpp | 2 ++ src/openrct2/world/Entrance.cpp | 4 +++ src/openrct2/world/Footpath.cpp | 22 ++++++++++++++++ src/openrct2/world/Fountain.cpp | 2 ++ src/openrct2/world/Map.cpp | 21 +++++++++++++++ src/openrct2/world/MapAnimation.cpp | 26 +++++++++++++++++-- src/openrct2/world/Park.cpp | 2 ++ src/openrct2/world/Scenery.cpp | 5 ++++ src/openrct2/world/Sprite.cpp | 2 ++ src/openrct2/world/TileInspector.cpp | 8 ++++++ src/openrct2/world/Wall.cpp | 4 +++ 25 files changed, 198 insertions(+), 4 deletions(-) diff --git a/src/openrct2/paint/VirtualFloor.cpp b/src/openrct2/paint/VirtualFloor.cpp index 44c55cd4b5..ff86d15680 100644 --- a/src/openrct2/paint/VirtualFloor.cpp +++ b/src/openrct2/paint/VirtualFloor.cpp @@ -243,6 +243,8 @@ static void virtual_floor_get_tile_properties( // * Walls / banners, which are displayed as occupied edges // * Ghost objects, which are displayed as lit squares TileElement* tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return; do { int32_t elementType = tileElement->GetType(); diff --git a/src/openrct2/paint/tile_element/Paint.TileElement.cpp b/src/openrct2/paint/tile_element/Paint.TileElement.cpp index 730a4e5409..682172b474 100644 --- a/src/openrct2/paint/tile_element/Paint.TileElement.cpp +++ b/src/openrct2/paint/tile_element/Paint.TileElement.cpp @@ -155,6 +155,8 @@ static void sub_68B3FB(paint_session* session, int32_t x, int32_t y) session->MapPosition.y = y; TileElement* tile_element = map_get_first_element_at(x >> 5, y >> 5); + if (tile_element == nullptr) + return; uint8_t rotation = session->CurrentRotation; bool partOfVirtualFloor = false; diff --git a/src/openrct2/peep/Guest.cpp b/src/openrct2/peep/Guest.cpp index 2ede34f725..8402351004 100644 --- a/src/openrct2/peep/Guest.cpp +++ b/src/openrct2/peep/Guest.cpp @@ -959,6 +959,8 @@ void Guest::Tick128UpdateGuest(int32_t index) bool found = false; do { + if (tileElement == nullptr) + break; if (tileElement->GetType() != TILE_ELEMENT_TYPE_PATH) continue; if (tileElement->base_height != next_z) @@ -2948,7 +2950,8 @@ static PeepThoughtType peep_assess_surroundings(int16_t centre_x, int16_t centre for (int16_t y = initial_y; y < final_y; y += 32) { TileElement* tileElement = map_get_first_element_at(x / 32, y / 32); - + if (tileElement == nullptr) + continue; do { Ride* ride; @@ -4176,6 +4179,8 @@ void Guest::UpdateRideLeaveVehicle() continue; TileElement* inner_map = map_get_first_element_at(vehicle->track_x / 32, vehicle->track_y / 32); + if (inner_map == nullptr) + continue; for (;; inner_map++) { if (inner_map->GetType() != TILE_ELEMENT_TYPE_TRACK) @@ -4937,6 +4942,8 @@ void Guest::UpdateRideMazePathfinding() maze_type mazeType = maze_type::invalid; auto tileElement = map_get_first_element_at(targetLoc.x / 32, targetLoc.y / 32); + if (tileElement == nullptr) + return; do { if (stationHeight != tileElement->base_height) @@ -5033,6 +5040,8 @@ void Guest::UpdateRideLeaveExit() // Find the station track element TileElement* tileElement = map_get_first_element_at(targetLoc.x / 32, targetLoc.y / 32); + if (tileElement == nullptr) + return; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_PATH) @@ -5452,6 +5461,8 @@ void Guest::UpdateWalking() return; TileElement* tileElement = map_get_first_element_at(next_x / 32, next_y / 32); + if (tileElement == nullptr) + return; for (;; tileElement++) { @@ -5868,6 +5879,8 @@ void Guest::UpdateUsingBin() } TileElement* tileElement = map_get_first_element_at(next_x / 32, next_y / 32); + if (tileElement == nullptr) + return; for (;; tileElement++) { @@ -6036,6 +6049,8 @@ bool Guest::UpdateWalkingFindBench() return false; TileElement* tileElement = map_get_first_element_at(next_x / 32, next_y / 32); + if (tileElement == nullptr) + return false; for (;; tileElement++) { @@ -6131,6 +6146,8 @@ bool Guest::UpdateWalkingFindBin() return false; TileElement* tileElement = map_get_first_element_at(peep->next_x / 32, peep->next_y / 32); + if (tileElement == nullptr) + return false; for (;; tileElement++) { @@ -6232,6 +6249,8 @@ static void peep_update_walking_break_scenery(Peep* peep) return; TileElement* tileElement = map_get_first_element_at(peep->next_x / 32, peep->next_y / 32); + if (tileElement == nullptr) + return; for (;; tileElement++) { @@ -6875,6 +6894,8 @@ void Guest::UpdateSpriteType() TileElement* tileElement = map_get_first_element_at(x / 32, y / 32); while (true) { + if (tileElement == nullptr) + break; if ((z / 8) < tileElement->base_height) break; diff --git a/src/openrct2/peep/GuestPathfinding.cpp b/src/openrct2/peep/GuestPathfinding.cpp index fe97345d05..8fb43c4f39 100644 --- a/src/openrct2/peep/GuestPathfinding.cpp +++ b/src/openrct2/peep/GuestPathfinding.cpp @@ -239,6 +239,8 @@ static uint8_t footpath_element_next_in_direction(TileCoordsXYZ loc, PathElement nextTileElement = map_get_first_element_at(loc.x, loc.y); do { + if (nextTileElement == nullptr) + break; if (nextTileElement->IsGhost()) continue; if (nextTileElement->GetType() != TILE_ELEMENT_TYPE_PATH) @@ -1209,6 +1211,8 @@ Direction peep_pathfind_choose_direction(TileCoordsXYZ loc, Peep* peep) bool isThin = false; do { + if (dest_tile_element == nullptr) + break; if (dest_tile_element->base_height != loc.z) continue; if (dest_tile_element->GetType() != TILE_ELEMENT_TYPE_PATH) @@ -1768,6 +1772,8 @@ static void get_ride_queue_end(TileCoordsXYZ& loc) tileElement = map_get_first_element_at(nextTile.x, nextTile.y); found = false; + if (tileElement == nullptr) + break; do { if (tileElement == firstPathElement) diff --git a/src/openrct2/peep/Peep.cpp b/src/openrct2/peep/Peep.cpp index 226afbcc0a..7a1f9c1f9b 100644 --- a/src/openrct2/peep/Peep.cpp +++ b/src/openrct2/peep/Peep.cpp @@ -484,6 +484,8 @@ bool Peep::CheckForPath() do { + if (tile_element == nullptr) + break; if (tile_element->GetType() == map_type) { if (height == tile_element->base_height) @@ -2541,6 +2543,8 @@ static void peep_interact_with_entrance(Peep* peep, int16_t x, int16_t y, TileEl TileElement* nextTileElement = map_get_first_element_at(next_x / 32, next_y / 32); do { + if (nextTileElement == nullptr) + break; if (nextTileElement->GetType() != TILE_ELEMENT_TYPE_PATH) continue; @@ -3092,6 +3096,8 @@ void Peep::PerformNextAction(uint8_t& pathing_result, TileElement*& tile_result) } TileElement* tileElement = map_get_first_element_at(newLoc.x / 32, newLoc.y / 32); + if (tileElement == nullptr) + return; int16_t base_z = std::max(0, (z / 8) - 2); int16_t top_z = (z / 8) + 1; diff --git a/src/openrct2/peep/Staff.cpp b/src/openrct2/peep/Staff.cpp index 63769dd5fc..1f5dc7de70 100644 --- a/src/openrct2/peep/Staff.cpp +++ b/src/openrct2/peep/Staff.cpp @@ -268,6 +268,8 @@ bool staff_can_ignore_wide_flag(Peep* staff, int32_t x, int32_t y, uint8_t z, Ti /* Search through all adjacent map elements */ TileElement* test_element = map_get_first_element_at(adjac_x / 32, adjac_y / 32); + if (test_element == nullptr) + return false; bool pathfound = false; bool widefound = false; do @@ -474,7 +476,8 @@ static uint8_t staff_handyman_direction_to_nearest_litter(Peep* peep) int16_t nextZ = ((peep->z + 8) & 0xFFF0) / 8; TileElement* tileElement = map_get_first_element_at(nextTile.x / 32, nextTile.y / 32); - + if (tileElement == nullptr) + return 0xFF; do { if (tileElement->base_height != nextZ) @@ -489,6 +492,8 @@ static uint8_t staff_handyman_direction_to_nearest_litter(Peep* peep) nextTile.y = (peep->y & 0xFFE0) + CoordsDirectionDelta[nextDirection].y; tileElement = map_get_first_element_at(nextTile.x / 32, nextTile.y / 32); + if (tileElement == nullptr) + return 0xFF; do { @@ -1250,6 +1255,8 @@ void Staff::UpdateWatering() int32_t actionY = next_y + CoordsDirectionDelta[var_37].y; TileElement* tile_element = map_get_first_element_at(actionX / 32, actionY / 32); + if (tile_element == nullptr) + return; do { @@ -1315,6 +1322,8 @@ void Staff::UpdateEmptyingBin() return; TileElement* tile_element = map_get_first_element_at(next_x / 32, next_y / 32); + if (tile_element == nullptr) + return; for (;; tile_element++) { diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index b7709065a4..a6da8c3088 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -2743,6 +2743,8 @@ private: for (int32_t y = 0; y < RCT1_MAX_MAP_SIZE; y++) { TileElement* tileElement = map_get_first_element_at(x, y); + if (tileElement == nullptr) + continue; do { if (tileElement->GetType() == TILE_ELEMENT_TYPE_WALL) @@ -2998,6 +3000,8 @@ private: for (int32_t y = 0; y < RCT1_MAX_MAP_SIZE; y++) { TileElement* tileElement = map_get_first_element_at(x, y); + if (tileElement == nullptr) + continue; do { if (tileElement->GetType() == TILE_ELEMENT_TYPE_TRACK) diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index b526d8c9f7..0f0f52e676 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -4944,6 +4944,8 @@ static bool ride_initialise_cable_lift_track(Ride* ride, bool isApplying) bool success = false; TileElement* tileElement = map_get_first_element_at(location.x, location.y); + if (tileElement == nullptr) + return success; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK) @@ -5182,6 +5184,8 @@ static TileElement* loc_6B4F6B(ride_id_t rideIndex, int32_t x, int32_t y) return nullptr; TileElement* tileElement = map_get_first_element_at(x / 32, y / 32); + if (tileElement == nullptr) + return nullptr; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK) @@ -6251,6 +6255,8 @@ void ride_get_entrance_or_exit_position_from_screen_position( if (mapX >= 0 && mapY >= 0 && mapX < (256 * 32) && mapY < (256 * 32)) { tileElement = map_get_first_element_at(mapX >> 5, mapY >> 5); + if (tileElement == nullptr) + continue; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK) @@ -6306,6 +6312,8 @@ void ride_get_entrance_or_exit_position_from_screen_position( mapX -= CoordsDirectionDelta[direction].x; mapY -= CoordsDirectionDelta[direction].y; tileElement = map_get_first_element_at(mapX >> 5, mapY >> 5); + if (tileElement == nullptr) + break; bool goToNextTile = false; do @@ -6648,6 +6656,8 @@ static int32_t ride_get_track_length(Ride* ride) z = ride->stations[i].Height; tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + continue; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK) @@ -6904,6 +6914,8 @@ void sub_6CB945(Ride* ride) location.y -= CoordsDirectionDelta[direction].y; } tileElement = map_get_first_element_at(location.x >> 5, location.y >> 5); + if (tileElement == nullptr) + break; bool trackFound = false; do @@ -6951,6 +6963,8 @@ void sub_6CB945(Ride* ride) bool trackFound = false; tileElement = map_get_first_element_at(blockLocation.x >> 5, blockLocation.y >> 5); + if (tileElement == nullptr) + break; do { if (blockLocation.z != tileElement->base_height) @@ -7016,6 +7030,8 @@ void sub_6CB945(Ride* ride) CoordsXY location = { locationCoords.x * 32, locationCoords.y * 32 }; TileElement* tileElement = map_get_first_element_at(location.x >> 5, location.y >> 5); + if (tileElement == nullptr) + continue; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_ENTRANCE) @@ -7031,6 +7047,8 @@ void sub_6CB945(Ride* ride) bool shouldRemove = true; TileElement* trackElement = map_get_first_element_at(nextLocation.x >> 5, nextLocation.y >> 5); + if (trackElement == nullptr) + continue; do { if (trackElement->GetType() != TILE_ELEMENT_TYPE_TRACK) diff --git a/src/openrct2/ride/RideRatings.cpp b/src/openrct2/ride/RideRatings.cpp index 401127bf01..26af55bf46 100644 --- a/src/openrct2/ride/RideRatings.cpp +++ b/src/openrct2/ride/RideRatings.cpp @@ -207,6 +207,11 @@ static void ride_ratings_update_state_2() int32_t trackType = gRideRatingsCalcData.proximity_track_type; TileElement* tileElement = map_get_first_element_at(x, y); + if (tileElement == nullptr) + { + gRideRatingsCalcData.state = RIDE_RATINGS_STATE_FIND_NEXT_RIDE; + return; + } do { if (tileElement->IsGhost()) @@ -313,6 +318,11 @@ static void ride_ratings_update_state_5() int32_t trackType = gRideRatingsCalcData.proximity_track_type; TileElement* tileElement = map_get_first_element_at(x, y); + if (tileElement == nullptr) + { + gRideRatingsCalcData.state = RIDE_RATINGS_STATE_FIND_NEXT_RIDE; + return; + } do { if (tileElement->IsGhost()) @@ -419,6 +429,8 @@ static void ride_ratings_score_close_proximity_in_direction(TileElement* inputTi return; TileElement* tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return; do { if (tileElement->IsGhost()) @@ -471,6 +483,8 @@ static void ride_ratings_score_close_proximity_in_direction(TileElement* inputTi static void ride_ratings_score_close_proximity_loops_helper(TileElement* inputTileElement, int32_t x, int32_t y) { TileElement* tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return; do { if (tileElement->IsGhost()) @@ -545,6 +559,8 @@ static void ride_ratings_score_close_proximity(TileElement* inputTileElement) int32_t x = gRideRatingsCalcData.proximity_x; int32_t y = gRideRatingsCalcData.proximity_y; TileElement* tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return; do { if (tileElement->IsGhost()) @@ -1438,6 +1454,8 @@ static int32_t ride_ratings_get_scenery_score(Ride* ride) { // Count scenery items on this tile TileElement* tileElement = map_get_first_element_at(xx, yy); + if (tileElement == nullptr) + continue; do { if (tileElement->IsGhost()) diff --git a/src/openrct2/ride/Station.cpp b/src/openrct2/ride/Station.cpp index 2cde4e11b4..891ddd94d9 100644 --- a/src/openrct2/ride/Station.cpp +++ b/src/openrct2/ride/Station.cpp @@ -340,6 +340,8 @@ TileElement* ride_get_station_start_track_element(Ride* ride, int32_t stationInd // Find the station track element TileElement* tileElement = map_get_first_element_at(x, y); + if (tileElement == nullptr) + return nullptr; do { if (tileElement->GetType() == TILE_ELEMENT_TYPE_TRACK && z == tileElement->base_height) @@ -354,6 +356,8 @@ TileElement* ride_get_station_exit_element(int32_t x, int32_t y, int32_t z) { // Find the station track element TileElement* tileElement = map_get_first_element_at(x, y); + if (tileElement == nullptr) + return nullptr; do { if (tileElement == nullptr) diff --git a/src/openrct2/ride/Track.cpp b/src/openrct2/ride/Track.cpp index b74b85a7ac..95c047ad6c 100644 --- a/src/openrct2/ride/Track.cpp +++ b/src/openrct2/ride/Track.cpp @@ -599,6 +599,8 @@ const rct_preview_track* get_track_def_from_ride_index(ride_id_t rideIndex, int3 static TileElement* find_station_element(int32_t x, int32_t y, int32_t z, int32_t direction, ride_id_t rideIndex) { TileElement* tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return nullptr; do { if (z != tileElement->base_height) diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index c0a64337e0..5239d47cd7 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -433,6 +433,8 @@ rct_string_id TrackDesign::CreateTrackDesignMaze(const Ride& ride) CoordsXY exitLoc = { location.x * 32, location.y * 32 }; tileElement = map_get_first_element_at(location.x, location.y); + if (tileElement == nullptr) + return STR_TRACK_TOO_LARGE_OR_TOO_MUCH_SCENERY; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_ENTRANCE) diff --git a/src/openrct2/ride/TrackDesignSave.cpp b/src/openrct2/ride/TrackDesignSave.cpp index 4dbc0c7a75..05bfcbddf1 100644 --- a/src/openrct2/ride/TrackDesignSave.cpp +++ b/src/openrct2/ride/TrackDesignSave.cpp @@ -525,6 +525,8 @@ static void track_design_save_select_nearby_scenery_for_tile(ride_id_t rideIndex for (int32_t x = cx - TRACK_NEARBY_SCENERY_DISTANCE; x <= cx + TRACK_NEARBY_SCENERY_DISTANCE; x++) { tileElement = map_get_first_element_at(x, y); + if (tileElement == nullptr) + continue; do { int32_t interactionType = VIEWPORT_INTERACTION_ITEM_NONE; diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index 14c87a4280..6442bc48de 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -1830,6 +1830,8 @@ static void vehicle_update_measurements(rct_vehicle* vehicle) // Set tile_element to first element. Since elements aren't always ordered by base height, // we must start at the first element and iterate through each tile element. auto tile_element = map_get_first_element_at(x / 32, y / 32); + if (tile_element == nullptr) + return; bool cover_found = false; do @@ -4635,6 +4637,8 @@ static void vehicle_update_boat_location(rct_vehicle* vehicle) static bool vehicle_boat_is_location_accessible(const TileCoordsXYZ& location) { TileElement* tileElement = map_get_first_element_at(location.x, location.y); + if (tileElement == nullptr) + return false; do { if (tileElement->IsGhost()) diff --git a/src/openrct2/world/Banner.cpp b/src/openrct2/world/Banner.cpp index 7553ac9156..4ca8242390 100644 --- a/src/openrct2/world/Banner.cpp +++ b/src/openrct2/world/Banner.cpp @@ -81,6 +81,8 @@ static uint8_t banner_get_ride_index_at(int32_t x, int32_t y, int32_t z) { TileElement* tileElement = map_get_first_element_at(x >> 5, y >> 5); ride_id_t resultRideIndex = RIDE_ID_NULL; + if (tileElement == nullptr) + return resultRideIndex; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK) diff --git a/src/openrct2/world/Entrance.cpp b/src/openrct2/world/Entrance.cpp index 8bd6f66292..a25d06f0b3 100644 --- a/src/openrct2/world/Entrance.cpp +++ b/src/openrct2/world/Entrance.cpp @@ -139,6 +139,8 @@ void maze_entrance_hedge_replacement(int32_t x, int32_t y, TileElement* tileElem ride_id_t rideIndex = tileElement->AsEntrance()->GetRideIndex(); tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK) @@ -175,6 +177,8 @@ void maze_entrance_hedge_removal(int32_t x, int32_t y, TileElement* tileElement) ride_id_t rideIndex = tileElement->AsEntrance()->GetRideIndex(); tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK) diff --git a/src/openrct2/world/Footpath.cpp b/src/openrct2/world/Footpath.cpp index 4e2def14b9..8b62b1b9ce 100644 --- a/src/openrct2/world/Footpath.cpp +++ b/src/openrct2/world/Footpath.cpp @@ -490,6 +490,8 @@ static TileElement* footpath_connect_corners_get_neighbour(int32_t x, int32_t y, } TileElement* tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return nullptr; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_PATH) @@ -662,6 +664,8 @@ static TileElement* footpath_get_element(int32_t x, int32_t y, int32_t z0, int32 int32_t slope; tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return nullptr; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_PATH) @@ -786,6 +790,8 @@ static void loc_6A6D7E( else { TileElement* tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return; do { switch (tileElement->GetType()) @@ -1294,6 +1300,8 @@ static int32_t footpath_is_connected_to_map_edge_recurse( return FOOTPATH_SEARCH_SUCCESS; tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return level == 1 ? FOOTPATH_SEARCH_NOT_FOUND : FOOTPATH_SEARCH_INCOMPLETE; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_PATH) @@ -1619,6 +1627,8 @@ void PathElement::SetShouldDrawPathOverSupports(bool on) static void footpath_clear_wide(int32_t x, int32_t y) { TileElement* tileElement = map_get_first_element_at(x / 32, y / 32); + if (tileElement == nullptr) + return; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_PATH) @@ -1636,6 +1646,8 @@ static void footpath_clear_wide(int32_t x, int32_t y) static TileElement* footpath_can_be_wide(int32_t x, int32_t y, uint8_t height) { TileElement* tileElement = map_get_first_element_at(x / 32, y / 32); + if (tileElement == nullptr) + return nullptr; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_PATH) @@ -1687,6 +1699,8 @@ void footpath_update_path_wide_flags(int32_t x, int32_t y) // y -= 0x20; TileElement* tileElement = map_get_first_element_at(x / 32, y / 32); + if (tileElement == nullptr) + return; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_PATH) @@ -1925,6 +1939,8 @@ static void footpath_remove_edges_towards_here( y += CoordsDirectionDelta[direction].y; tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_PATH) @@ -1954,6 +1970,8 @@ static void footpath_remove_edges_towards(int32_t x, int32_t y, int32_t z0, int3 } TileElement* tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_PATH) @@ -1991,6 +2009,8 @@ static void footpath_remove_edges_towards(int32_t x, int32_t y, int32_t z0, int3 bool tile_element_wants_path_connection_towards(TileCoordsXYZD coords, const TileElement* const elementToBeRemoved) { TileElement* tileElement = map_get_first_element_at(coords.x, coords.y); + if (tileElement == nullptr) + return false; do { // Don't check the element that gets removed @@ -2080,6 +2100,8 @@ static void footpath_fix_corners_around(int32_t x, int32_t y, TileElement* pathE continue; TileElement* tileElement = map_get_first_element_at(x + xOffset, y + yOffset); + if (tileElement == nullptr) + continue; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_PATH) diff --git a/src/openrct2/world/Fountain.cpp b/src/openrct2/world/Fountain.cpp index cecf720a41..e991f79fb3 100644 --- a/src/openrct2/world/Fountain.cpp +++ b/src/openrct2/world/Fountain.cpp @@ -237,6 +237,8 @@ bool JumpingFountain::IsJumpingFountain(const int32_t newType, const CoordsXYZ n : PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER; TileElement* tileElement = map_get_first_element_at(newLoc.x / 32, newLoc.y / 32); + if (tileElement == nullptr) + return false; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_PATH) diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index 22af58af05..5538323ed0 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -605,6 +605,9 @@ bool map_coord_is_connected(const TileCoordsXYZ& loc, uint8_t faceDirection) { TileElement* tileElement = map_get_first_element_at(loc.x, loc.y); + if (tileElement == nullptr) + return false; + do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_PATH) @@ -1096,6 +1099,8 @@ void map_reorganise_elements() for (int32_t x = 0; x < MAXIMUM_MAP_SIZE_TECHNICAL; x++) { TileElement* startElement = map_get_first_element_at(x, y); + if (startElement == nullptr) + continue; TileElement* endElement = startElement; while (!(endElement++)->IsLastForTile()) ; @@ -1310,6 +1315,8 @@ bool map_can_construct_with_clear_at( } TileElement* tileElement = map_get_first_element_at(x / 32, y / 32); + if (tileElement == nullptr) + return false; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_SURFACE) @@ -1728,6 +1735,8 @@ static void clear_elements_at(const CoordsXY& loc) gPeepSpawns.end()); TileElement* tileElement = map_get_first_element_at(loc.x / 32, loc.y / 32); + if (tileElement == nullptr) + return; // Remove all elements except the last one while (!tileElement->IsLastForTile()) @@ -2142,6 +2151,8 @@ void map_clear_all_elements() TrackElement* map_get_track_element_at(int32_t x, int32_t y, int32_t z) { TileElement* tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return nullptr; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK) @@ -2164,6 +2175,8 @@ TrackElement* map_get_track_element_at(int32_t x, int32_t y, int32_t z) TileElement* map_get_track_element_at_of_type(int32_t x, int32_t y, int32_t z, int32_t trackType) { TileElement* tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return nullptr; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK) @@ -2264,6 +2277,8 @@ TrackElement* map_get_track_element_at_of_type_seq(CoordsXYZD location, int32_t TileElement* map_get_track_element_at_of_type_from_ride(int32_t x, int32_t y, int32_t z, int32_t trackType, ride_id_t rideIndex) { TileElement* tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return nullptr; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK) @@ -2290,6 +2305,8 @@ TileElement* map_get_track_element_at_of_type_from_ride(int32_t x, int32_t y, in TileElement* map_get_track_element_at_from_ride(int32_t x, int32_t y, int32_t z, ride_id_t rideIndex) { TileElement* tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return nullptr; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK) @@ -2316,6 +2333,8 @@ TileElement* map_get_track_element_at_with_direction_from_ride( int32_t x, int32_t y, int32_t z, int32_t direction, ride_id_t rideIndex) { TileElement* tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return nullptr; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK) @@ -2346,6 +2365,8 @@ void map_offset_with_rotation(int16_t* x, int16_t* y, int16_t offsetX, int16_t o WallElement* map_get_wall_element_at(int32_t x, int32_t y, int32_t z, int32_t direction) { TileElement* tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return nullptr; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_WALL) diff --git a/src/openrct2/world/MapAnimation.cpp b/src/openrct2/world/MapAnimation.cpp index 85adc90060..f05a9b4e9d 100644 --- a/src/openrct2/world/MapAnimation.cpp +++ b/src/openrct2/world/MapAnimation.cpp @@ -91,6 +91,8 @@ void map_animation_invalidate_all() static bool map_animation_invalidate_ride_entrance(int32_t x, int32_t y, int32_t baseZ) { auto tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return true; do { if (tileElement->base_height != baseZ) @@ -125,6 +127,8 @@ static bool map_animation_invalidate_queue_banner(int32_t x, int32_t y, int32_t TileElement* tileElement; tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return true; do { if (tileElement->base_height != baseZ) @@ -160,6 +164,8 @@ static bool map_animation_invalidate_small_scenery(int32_t x, int32_t y, int32_t Peep* peep; tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return true; do { if (tileElement->base_height != baseZ) @@ -231,6 +237,8 @@ static bool map_animation_invalidate_park_entrance(int32_t x, int32_t y, int32_t TileElement* tileElement; tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return true; do { if (tileElement->base_height != baseZ) @@ -259,6 +267,8 @@ static bool map_animation_invalidate_track_waterfall(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) @@ -286,6 +296,8 @@ static bool map_animation_invalidate_track_rapids(int32_t x, int32_t y, int32_t TileElement* tileElement; tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return true; do { if (tileElement->base_height != baseZ) @@ -313,10 +325,10 @@ static bool map_animation_invalidate_track_onridephoto(int32_t x, int32_t y, int TileElement* tileElement; tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return true; do { - if (tileElement == nullptr) - break; if (tileElement->base_height != baseZ) continue; if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK) @@ -380,6 +392,8 @@ static bool map_animation_invalidate_track_spinningtunnel(int32_t x, int32_t y, TileElement* tileElement; tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return true; do { if (tileElement->base_height != baseZ) @@ -417,6 +431,8 @@ static bool map_animation_invalidate_banner(int32_t x, int32_t y, int32_t baseZ) TileElement* tileElement; tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return true; do { if (tileElement->base_height != baseZ) @@ -443,6 +459,8 @@ static bool map_animation_invalidate_large_scenery(int32_t x, int32_t y, int32_t bool wasInvalidated = false; tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return true; do { if (tileElement->base_height != baseZ) @@ -476,6 +494,8 @@ static bool map_animation_invalidate_wall_door(int32_t x, int32_t y, int32_t bas bool removeAnimation = true; tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return removeAnimation; do { if (tileElement->base_height != baseZ) @@ -536,6 +556,8 @@ static bool map_animation_invalidate_wall(int32_t x, int32_t y, int32_t baseZ) bool wasInvalidated = false; tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return true; do { if (tileElement->base_height != baseZ) diff --git a/src/openrct2/world/Park.cpp b/src/openrct2/world/Park.cpp index 83b549f4af..598f26a169 100644 --- a/src/openrct2/world/Park.cpp +++ b/src/openrct2/world/Park.cpp @@ -117,6 +117,8 @@ void update_park_fences(const CoordsXY coords) bool fenceRequired = true; TileElement* tileElement = map_get_first_element_at(coords.x / 32, coords.y / 32); + if (tileElement == nullptr) + return; // If an entrance element do not place flags around surface do { diff --git a/src/openrct2/world/Scenery.cpp b/src/openrct2/world/Scenery.cpp index 9114aa3cfb..f5df790a29 100644 --- a/src/openrct2/world/Scenery.cpp +++ b/src/openrct2/world/Scenery.cpp @@ -73,6 +73,8 @@ void scenery_update_tile(int32_t x, int32_t y) TileElement* tileElement; tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return; do { // Ghosts are purely this-client-side and should not cause any interaction, @@ -200,6 +202,9 @@ void scenery_remove_ghost_tool_placement() do { + if (tileElement == nullptr) + break; + if (tileElement->GetType() != TILE_ELEMENT_TYPE_PATH) continue; diff --git a/src/openrct2/world/Sprite.cpp b/src/openrct2/world/Sprite.cpp index 5bbdfebf92..7d43e2e235 100644 --- a/src/openrct2/world/Sprite.cpp +++ b/src/openrct2/world/Sprite.cpp @@ -711,6 +711,8 @@ static bool litter_can_be_at(int32_t x, int32_t y, int32_t z) return false; tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return false; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_PATH) diff --git a/src/openrct2/world/TileInspector.cpp b/src/openrct2/world/TileInspector.cpp index baeda71cc0..508f32c8b6 100644 --- a/src/openrct2/world/TileInspector.cpp +++ b/src/openrct2/world/TileInspector.cpp @@ -355,6 +355,8 @@ GameActionResult::Ptr tile_inspector_sort_elements_at(CoordsXY loc, bool isExecu if (isExecuting) { const TileElement* const firstElement = map_get_first_element_at(loc.x / 32, loc.y / 32); + if (firstElement == nullptr) + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); // Count elements on tile int32_t numElement = 0; @@ -789,6 +791,9 @@ GameActionResult::Ptr tile_inspector_track_base_height_offset( TileElement* tileElement = map_get_first_element_at(elem.x >> 5, elem.y >> 5); do { + if (tileElement == nullptr) + break; + if (tileElement->base_height != elemZ / 8) continue; @@ -893,6 +898,9 @@ GameActionResult::Ptr tile_inspector_track_set_chain( TileElement* tileElement = map_get_first_element_at(elem.x >> 5, elem.y >> 5); do { + if (tileElement == nullptr) + break; + if (tileElement->base_height != elemZ / 8) continue; diff --git a/src/openrct2/world/Wall.cpp b/src/openrct2/world/Wall.cpp index b3bd57f8ee..67aec95153 100644 --- a/src/openrct2/world/Wall.cpp +++ b/src/openrct2/world/Wall.cpp @@ -41,6 +41,8 @@ void wall_remove_at(int32_t x, int32_t y, int32_t z0, int32_t z1) z1 /= 8; repeat: tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_WALL) @@ -75,6 +77,8 @@ void wall_remove_intersecting_walls(int32_t x, int32_t y, int32_t z0, int32_t z1 TileElement* tileElement; tileElement = map_get_first_element_at(x >> 5, y >> 5); + if (tileElement == nullptr) + return; do { if (tileElement->GetType() != TILE_ELEMENT_TYPE_WALL)