From d6604db5b4cf2afef96c872efeba88f450398188 Mon Sep 17 00:00:00 2001 From: Florian Fontan Date: Wed, 23 Sep 2026 12:39:24 +0200 Subject: [PATCH] Fix out-of-bounds read in dynamic_programming_bellman_word_ram The final scan for the optimal value used 'optimal_value == 0' as its only stopping condition. Weight 0 is always reachable, so when it is the optimal value (no item, or no item fitting in the capacity), the scan went past word 0 and read 'output.values[-1]'. Stop the scan at word 0. --- src/algorithms/dynamic_programming_bellman.cpp | 4 +++- .../dynamic_programming_bellman_test.cpp | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/algorithms/dynamic_programming_bellman.cpp b/src/algorithms/dynamic_programming_bellman.cpp index 87c7e9b..5a12f06 100644 --- a/src/algorithms/dynamic_programming_bellman.cpp +++ b/src/algorithms/dynamic_programming_bellman.cpp @@ -197,7 +197,9 @@ DynamicProgrammingBellmanWordRamOutput subsetsumsolver::dynamic_programming_bell } Weight optimal_value = 0; - for (Weight word = capacity_number_of_words; optimal_value == 0; --word) { + for (Weight word = capacity_number_of_words; + word >= 0 && optimal_value == 0; + --word) { if (output.values[word] == 0) continue; for (int bit = 63; bit >= 0; --bit) { diff --git a/test/algorithms/dynamic_programming_bellman_test.cpp b/test/algorithms/dynamic_programming_bellman_test.cpp index ee6f561..9131403 100644 --- a/test/algorithms/dynamic_programming_bellman_test.cpp +++ b/test/algorithms/dynamic_programming_bellman_test.cpp @@ -1,6 +1,7 @@ #include "subsetsumsolver/tests.hpp" #include "subsetsumsolver/algorithms/dynamic_programming_bellman.hpp" +#include "subsetsumsolver/instance_builder.hpp" using namespace subsetsumsolver; @@ -100,3 +101,19 @@ INSTANTIATE_TEST_SUITE_P( get_pthree_instance_paths(1000), get_psix_instance_paths(10), }))); + +TEST(SubsetSumDynamicProgrammingBellmanWordRam, NothingButZeroReachable) +{ + // Only weight '0' is reachable: the final scan for the optimal value + // must stop at word '0' instead of reading out of bounds. + for (Weight item_weight: {-1, 200}) { + InstanceBuilder instance_builder; + instance_builder.set_capacity(100); + if (item_weight >= 0) + instance_builder.add_item(item_weight); + const Instance instance = instance_builder.build(); + auto output = dynamic_programming_bellman_word_ram(instance); + EXPECT_EQ(output.value, 0); + EXPECT_EQ(output.bound, 0); + } +}