From 7727748b76c99c52cacd8b075af7ce05698fa8c0 Mon Sep 17 00:00:00 2001 From: jerrrrycho Date: Thu, 15 Oct 2026 21:28:20 +0200 Subject: [PATCH] fix(ai): keep the light selector lookup within its table, Sonar findings of the handover - the light selector size comes from the vehicle definition (LightsList Size) and isn't limited, while the table holds 18 positions; a bigger selector read past the table, and so did a table index other than the front or rear one. Only the positions the table holds are looked at now, and the selector stays where it is for a bad table index (cpp:S2259), - the lambdas of the handover capture what they use explicitly (cpp:S3608), - the chained assignments resetting the headlight state on the AI taking over are split (cpp:S1121). --- tests/unit/test_handover.cpp | 18 ++++++++++++++++++ vehicle/Driver.cpp | 6 ++++-- vehicle/handover.cpp | 13 ++++++++----- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/tests/unit/test_handover.cpp b/tests/unit/test_handover.cpp index d4583eb0..ff4a0df8 100644 --- a/tests/unit/test_handover.cpp +++ b/tests/unit/test_handover.cpp @@ -109,6 +109,24 @@ TEST_CASE("handover: the light selector moves to the position giving the head li } } +TEST_CASE("handover: the light selector stays within its table") { + auto cab{cab_vehicle()}; + + SUBCASE("selector bigger than the table, as a vehicle definition can declare") { + // only the positions the table holds are looked at, the rest can't match + for (auto &table : cab->Lights) { + std::fill(std::begin(table) + cab->LightsPosNo, std::end(table), 0); + } + cab->LightsPosNo = 100; + CHECK(handover::light_selector_position(cab.mover(), end::front, pc1, allheadlights) == 2); + CHECK(handover::light_selector_position(cab.mover(), end::front, light::headlight_left, allheadlights) == 1); + } + SUBCASE("table other than the front or rear one: the selector stays") { + CHECK(handover::light_selector_position(cab.mover(), -1, pc1, allheadlights) == 1); + CHECK(handover::light_selector_position(cab.mover(), 2, pc1, allheadlights) == 1); + } +} + TEST_CASE("handover: the light selector already matching the lights stays") { auto cab{cab_vehicle()}; cab->LightsPos = 2; // Pc1 diff --git a/vehicle/Driver.cpp b/vehicle/Driver.cpp index 88145016..5bbaa80e 100644 --- a/vehicle/Driver.cpp +++ b/vehicle/Driver.cpp @@ -5564,8 +5564,10 @@ void TController::TakeControl( bool const Aidriver, bool const Forcevehiclecheck pVehicle->Controller = AIdriver; // the AI doesn't operate the headlight dimmer, drop the state left by the human driver // so the lights set by the AI aren't hidden (dimmer in off position) or dimmed - pVehicle->HeadlightsAoff = pVehicle->HeadlightsBoff = false; - pVehicle->DimHeadlights = pVehicle->HighBeamLights = false; + pVehicle->HeadlightsAoff = false; + pVehicle->HeadlightsBoff = false; + pVehicle->DimHeadlights = false; + pVehicle->HighBeamLights = false; control_lights(); // reinicjalizacja swiatel mvOccupied->CabActivisation(true); iDirection = 0; // kierunek jazdy trzeba dopiero zgadnąć diff --git a/vehicle/handover.cpp b/vehicle/handover.cpp index e5ce5262..a36ccde8 100644 --- a/vehicle/handover.cpp +++ b/vehicle/handover.cpp @@ -30,14 +30,17 @@ void release_ai_controls(TMoverParameters &Occupied, TMoverParameters &Controlli } int light_selector_position(TMoverParameters const &Occupied, int const Lightstable, int const Headlights, int const Inventory) { - if (Occupied.LightsPosNo <= 0) { + // the selector size comes from the vehicle definition, the table holds a fixed number of positions + auto const positioncount{std::min(Occupied.LightsPosNo, static_cast(std::size(Occupied.Lights[0])))}; + if (positioncount <= 0 || Lightstable < 0 || Lightstable >= static_cast(std::size(Occupied.Lights))) { return Occupied.LightsPos; } - auto const lightsmatch{[&](int const Position) { return (Occupied.Lights[Lightstable][Position - 1] & Inventory) == Headlights; }}; - if (Occupied.LightsPos >= 1 && Occupied.LightsPos <= Occupied.LightsPosNo && lightsmatch(Occupied.LightsPos)) { + auto const &lights{Occupied.Lights[Lightstable]}; + auto const lightsmatch{[&lights, Inventory, Headlights](int const Position) { return (lights[Position - 1] & Inventory) == Headlights; }}; + if (Occupied.LightsPos >= 1 && Occupied.LightsPos <= positioncount && lightsmatch(Occupied.LightsPos)) { return Occupied.LightsPos; } - for (auto position = 1; position <= Occupied.LightsPosNo; ++position) { + for (auto position = 1; position <= positioncount; ++position) { if (lightsmatch(position)) { return position; } @@ -49,7 +52,7 @@ int dimmer_position(TMoverParameters const &Occupied, bool const Headlightson) { auto const &positions{Occupied.dimPositions}; auto const current{Occupied.modernDimmerPosition}; auto const count{static_cast(positions.size())}; - auto const isoff{[&](int const Position) { return Position < 0 || Position >= count || positions[Position].isOff; }}; + auto const isoff{[&positions, count](int const Position) { return Position < 0 || Position >= count || positions[Position].isOff; }}; if (false == Occupied.enableModernDimmer || false == Headlightson || false == isoff(current)) { return current;