From 6977da8cdfeae628fd1b1ee000dd28a7421a33ae Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 13 Mar 2026 11:54:20 +0100 Subject: [PATCH 1/3] fix: [Bug Report] osrm-routed segfaults/asserts Issue: https://github.com/Project-OSRM/osrm-backend/issues/7203 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- CHANGELOG.md | 1 + .../routing_algorithms/routing_base_mld.hpp | 2 +- unit_tests/engine/offline_facade.cpp | 25 +++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd79b14d084..dba7ec12246 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Unreleased - Changes from 6.0.0 - Routing: + - FIXED: Prevent MLD route queries from updating removed heap nodes, avoiding `osrm-routed` segfaults/asserts [#7203](https://github.com/Project-OSRM/osrm-backend/issues/7203) - FIXED: Crash when route starts or ends at `type=manoeuvre` relation via node [#7287](https://github.com/Project-OSRM/osrm-backend/issues/7287) - Extraction: - ADDED: Emit warning when ways reference nodes not present in input data [#1596](https://github.com/Project-OSRM/osrm-backend/issues/1596) diff --git a/include/engine/routing_algorithms/routing_base_mld.hpp b/include/engine/routing_algorithms/routing_base_mld.hpp index 2809790e408..49449012513 100644 --- a/include/engine/routing_algorithms/routing_base_mld.hpp +++ b/include/engine/routing_algorithms/routing_base_mld.hpp @@ -282,7 +282,7 @@ void insertOrUpdate(Heap &heap, { heap.Insert(node, weight, data); } - else if (weight < heapNode->weight) + else if (!heap.WasRemoved(node) && weight < heapNode->weight) { heapNode->data = data; heapNode->weight = weight; diff --git a/unit_tests/engine/offline_facade.cpp b/unit_tests/engine/offline_facade.cpp index 41af0ad3217..77cd58b099b 100644 --- a/unit_tests/engine/offline_facade.cpp +++ b/unit_tests/engine/offline_facade.cpp @@ -398,4 +398,29 @@ BOOST_AUTO_TEST_CASE(facade_uncompressed_methods) BOOST_CHECK_EQUAL(facade.GetUncompressedReverseDatasources(0).size(), 0); } +BOOST_AUTO_TEST_CASE(insert_or_update_skips_removed_nodes) +{ + using QueryHeap = + osrm::engine::SearchEngineData:: + QueryHeap; + + QueryHeap heap(4, 0); + const osrm::engine::MultiLayerDijkstraHeapData initial_data{SPECIAL_NODEID, false}; + const osrm::engine::MultiLayerDijkstraHeapData updated_data{1, true}; + + heap.Insert(1, {10}, initial_data); + BOOST_CHECK_EQUAL(heap.DeleteMin(), 1); + BOOST_CHECK(heap.WasRemoved(1)); + + osrm::engine::routing_algorithms::mld::insertOrUpdate(heap, 1, {5}, updated_data); + + BOOST_CHECK(heap.WasRemoved(1)); + BOOST_CHECK_EQUAL(from_alias(heap.GetKey(1)), 10); + + const auto heap_node = heap.GetHeapNodeIfWasInserted(1); + BOOST_REQUIRE(heap_node != nullptr); + BOOST_CHECK_EQUAL(heap_node->data.parent, SPECIAL_NODEID); + BOOST_CHECK_EQUAL(heap_node->data.from_clique_arc, false); +} + BOOST_AUTO_TEST_SUITE_END() From 74bcd599c0ff36118de3a1ab080ffd1644dbb6fd Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 13 Mar 2026 12:16:55 +0100 Subject: [PATCH 2/3] Fix formatting --- unit_tests/engine/offline_facade.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/unit_tests/engine/offline_facade.cpp b/unit_tests/engine/offline_facade.cpp index 77cd58b099b..4c3dfb6feed 100644 --- a/unit_tests/engine/offline_facade.cpp +++ b/unit_tests/engine/offline_facade.cpp @@ -400,9 +400,8 @@ BOOST_AUTO_TEST_CASE(facade_uncompressed_methods) BOOST_AUTO_TEST_CASE(insert_or_update_skips_removed_nodes) { - using QueryHeap = - osrm::engine::SearchEngineData:: - QueryHeap; + using QueryHeap = osrm::engine::SearchEngineData< + osrm::engine::routing_algorithms::offline::Algorithm>::QueryHeap; QueryHeap heap(4, 0); const osrm::engine::MultiLayerDijkstraHeapData initial_data{SPECIAL_NODEID, false}; From 52ba1436463fbe4cd28f56bc485b7ffb0f3a10be Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 20 Mar 2026 11:44:28 +0100 Subject: [PATCH 3/3] fix: move WasRemoved check to HeapNode to avoid implicit Heap template requirement The insertOrUpdate function was calling heap.WasRemoved(node), which added an implicit requirement on the Heap template parameter that could produce hard-to-decipher errors for Heap types that don't implement WasRemoved. Instead, add a WasRemoved() method directly to HeapNode (which, as a nested struct of QueryHeap, can access the private HeapContainer::INVALID_HANDLE), and call heapNode->WasRemoved() in insertOrUpdate. This keeps the removed- state check self-contained in the node and removes the extra constraint from the Heap template parameter. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- include/engine/routing_algorithms/routing_base_mld.hpp | 2 +- include/util/query_heap.hpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/engine/routing_algorithms/routing_base_mld.hpp b/include/engine/routing_algorithms/routing_base_mld.hpp index 49449012513..06374ada0fd 100644 --- a/include/engine/routing_algorithms/routing_base_mld.hpp +++ b/include/engine/routing_algorithms/routing_base_mld.hpp @@ -282,7 +282,7 @@ void insertOrUpdate(Heap &heap, { heap.Insert(node, weight, data); } - else if (!heap.WasRemoved(node) && weight < heapNode->weight) + else if (!heapNode->WasRemoved() && weight < heapNode->weight) { heapNode->data = data; heapNode->weight = weight; diff --git a/include/util/query_heap.hpp b/include/util/query_heap.hpp index 72b9e4b8860..f7bf71049db 100644 --- a/include/util/query_heap.hpp +++ b/include/util/query_heap.hpp @@ -154,6 +154,8 @@ class QueryHeap NodeID node; Weight weight; Data data; + + bool WasRemoved() const { return handle == HeapContainer::INVALID_HANDLE; } }; template explicit QueryHeap(StorageArgs... args) : node_index(args...)