Fix: Check for engine variant loops during NewGRF initialization. (#11343)

Invalid NewGRFs could set up an engine variant loop that never ends. This
was checked for in some places that evaluated variants, but not all. In
most cases this would result in the engines not appearing, but could
potentially cause an infinite loop and crash.

Instead, during NewGRF initialization detect loops and remove invalid
variants before setting display flags.
This commit is contained in:
Peter Nelson
2023-10-03 12:14:32 +01:00
committed by GitHub
parent 077b08bbfa
commit 5869f790d8
3 changed files with 30 additions and 12 deletions

View File

@@ -9125,12 +9125,9 @@ static void FinaliseEngineArray()
}
}
/* Do final mapping on variant engine ID and set appropriate flags on variant engine */
/* Do final mapping on variant engine ID. */
if (e->info.variant_id != INVALID_ENGINE) {
e->info.variant_id = GetNewEngineID(e->grf_prop.grffile, e->type, e->info.variant_id);
if (e->info.variant_id != INVALID_ENGINE) {
Engine::Get(e->info.variant_id)->display_flags |= EngineDisplayFlags::HasVariants | EngineDisplayFlags::IsFolded;
}
}
if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
@@ -9162,6 +9159,26 @@ static void FinaliseEngineArray()
}
}
}
/* Check engine variants don't point back on themselves (either directly or via a loop) then set appropriate flags
* on variant engine. This is performed separately as all variant engines need to have been resolved. */
for (Engine *e : Engine::Iterate()) {
EngineID parent = e->info.variant_id;
while (parent != INVALID_ENGINE) {
parent = Engine::Get(parent)->info.variant_id;
if (parent != e->index) continue;
/* Engine looped back on itself, so clear the variant. */
e->info.variant_id = INVALID_ENGINE;
GrfMsg(1, "FinaliseEngineArray: Variant of engine {:x} in '{}' loops back on itself", _engine_mngr[e->index].internal_id, e->GetGRF()->filename);
break;
}
if (e->info.variant_id != INVALID_ENGINE) {
Engine::Get(e->info.variant_id)->display_flags |= EngineDisplayFlags::HasVariants | EngineDisplayFlags::IsFolded;
}
}
}
/** Check for invalid cargoes */