1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-22 14:24:33 +01:00

Fix #7052: Infinite loops occur in track circuit iteration

This commit is contained in:
Richard Jenkins
2018-01-20 21:51:26 +00:00
parent 104419f6b2
commit c76b075348
3 changed files with 57 additions and 10 deletions

View File

@@ -818,7 +818,7 @@ sint32 ride_find_track_gap(rct_xy_element *input, rct_xy_element *output)
if (w != nullptr && _rideConstructionState != RIDE_CONSTRUCTION_STATE_0 && _currentRideIndex == rideIndex)
ride_construction_invalidate_current_track();
bool counter = true;
bool moveSlowIt = true;
track_circuit_iterator_begin(&it, *input);
slowIt = it;
while (track_circuit_iterator_next(&it)) {
@@ -827,13 +827,12 @@ sint32 ride_find_track_gap(rct_xy_element *input, rct_xy_element *output)
return 1;
}
//#2081: prevent an infinite loop
counter = !counter;
if (counter) {
moveSlowIt = !moveSlowIt;
if (moveSlowIt)
{
track_circuit_iterator_next(&slowIt);
if (slowIt.currentZ == it.currentZ &&
slowIt.currentDirection == it.currentDirection &&
slowIt.current.x == it.current.x &&
slowIt.current.y == it.current.y) {
if (track_circuit_iterators_match(&it, &slowIt))
{
*output = it.current;
return 1;
}
@@ -4172,14 +4171,28 @@ static bool ride_check_track_contains_inversions(rct_xy_element *input, rct_xy_e
ride_construction_invalidate_current_track();
}
track_circuit_iterator it;
bool moveSlowIt = true;
track_circuit_iterator it, slowIt;
track_circuit_iterator_begin(&it, *input);
slowIt = it;
while (track_circuit_iterator_next(&it)) {
sint32 trackType = track_element_get_type(it.current.element);
if (TrackFlags[trackType] & TRACK_ELEM_FLAG_INVERSION_TO_NORMAL) {
*output = it.current;
return true;
}
// Prevents infinite loops
moveSlowIt = !moveSlowIt;
if (moveSlowIt)
{
track_circuit_iterator_next(&slowIt);
if (track_circuit_iterators_match(&it, &slowIt))
{
return false;
}
}
}
return false;
}
@@ -4203,14 +4216,28 @@ static bool ride_check_track_contains_banked(rct_xy_element *input, rct_xy_eleme
ride_construction_invalidate_current_track();
}
track_circuit_iterator it;
bool moveSlowIt = true;
track_circuit_iterator it, slowIt;
track_circuit_iterator_begin(&it, *input);
slowIt = it;
while (track_circuit_iterator_next(&it)) {
sint32 trackType = track_element_get_type(output->element);
if (TrackFlags[trackType] & TRACK_ELEM_FLAG_BANKED) {
*output = it.current;
return true;
}
// Prevents infinite loops
moveSlowIt = !moveSlowIt;
if (moveSlowIt)
{
track_circuit_iterator_next(&slowIt);
if (track_circuit_iterators_match(&it, &slowIt))
{
return false;
}
}
}
return false;
}
@@ -6991,7 +7018,7 @@ static sint32 ride_get_track_length(Ride * ride)
{
rct_window * w;
rct_tile_element * tileElement = nullptr;
track_circuit_iterator it;
track_circuit_iterator it, slowIt;
sint32 x = 0, y = 0, z, trackType, rideIndex, result;
bool foundTrack = false;
@@ -7033,12 +7060,23 @@ static sint32 ride_get_track_length(Ride * ride)
ride_construction_invalidate_current_track();
}
bool moveSlowIt = true;
result = 0;
track_circuit_iterator_begin(&it, {x, y, tileElement});
slowIt = it;
while (track_circuit_iterator_next(&it))
{
trackType = track_element_get_type(it.current.element);
result += TrackPieceLengths[trackType];
if (moveSlowIt)
{
track_circuit_iterator_next(&slowIt);
if (track_circuit_iterators_match(&it, &slowIt))
{
return 0;
}
}
}
return result;
}

View File

@@ -2402,6 +2402,14 @@ bool track_circuit_iterator_next(track_circuit_iterator * it)
}
}
bool track_circuit_iterators_match(const track_circuit_iterator * firstIt, const track_circuit_iterator * secondIt)
{
return (firstIt->currentZ == secondIt->currentZ &&
firstIt->currentDirection == secondIt->currentDirection &&
firstIt->current.x == secondIt->current.x &&
firstIt->current.y == secondIt->current.y);
}
void track_get_back(rct_xy_element * input, rct_xy_element * output)
{
rct_xy_element lastTrack;

View File

@@ -537,6 +537,7 @@ const rct_track_coordinates * get_track_coord_from_ride(Ride * ride, sint32 trac
void track_circuit_iterator_begin(track_circuit_iterator * it, rct_xy_element first);
bool track_circuit_iterator_previous(track_circuit_iterator * it);
bool track_circuit_iterator_next(track_circuit_iterator * it);
bool track_circuit_iterators_match(const track_circuit_iterator * firstIt, const track_circuit_iterator * secondIt);
void track_get_back(rct_xy_element * input, rct_xy_element * output);
void track_get_front(rct_xy_element * input, rct_xy_element * output);