From ccdcf03fa84c9eb2fc5ac0ee4d197a0fe19cb20a Mon Sep 17 00:00:00 2001 From: Codex instance Date: Thu, 30 Jul 2026 16:49:21 +0100 Subject: [PATCH 1/2] test: cover completed solver boards Exercise both the trivial order-1 solution and the feasible order-8 solution through the independent placement validator. With the existing completion ordering, the focused test reports a heap-buffer-overflow under AddressSanitizer before validation can run. Refs: #14 --- CMakeLists.txt | 1 + tests/tests.cc | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 56c52d0..a87e234 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,4 +15,5 @@ if(BUILD_TESTING) add_test(NAME construction COMMAND partridge_tests construction) add_test(NAME rendering COMMAND partridge_tests rendering) add_test(NAME solver-small COMMAND partridge_tests solver-small) + add_test(NAME solver-completion COMMAND partridge_tests solver-completion) endif() diff --git a/tests/tests.cc b/tests/tests.cc index e022ecc..939fc78 100644 --- a/tests/tests.cc +++ b/tests/tests.cc @@ -280,6 +280,19 @@ namespace { "result adapter did not convert encoded placement coordinates"); return failures; } + + auto test_solver_completion() -> int { + int failures = 0; + for (auto const order: std::array{1, 8}) { + auto const solution = find_solution(order); + auto const validation = validate(order, solution); + failures += expect( + validation.valid(), + "solver returned an invalid order-" + std::to_string(order) + + " solution:\n" + validation.text()); + } + return failures; + } } int main(int argc, char **argv) { @@ -301,6 +314,9 @@ int main(int argc, char **argv) { if (test == "solver-small") { return test_small_solver(); } + if (test == "solver-completion") { + return test_solver_completion(); + } std::cerr << "unknown test: " << test << '\n'; return 2; } -- 2.54.0 From ce39d0a4d051d14071ef658c8d5cd86a8eb8b22f Mon Sep 17 00:00:00 2001 From: Codex instance Date: Thu, 30 Jul 2026 16:50:19 +0100 Subject: [PATCH 2/2] solver: check completion before probing square next_pos() returns the grid end sentinel when a placement completes the board. Avoid passing that sentinel to largest_square(), which requires an in-range position and otherwise reads past the grid. Tests: Debug, Release, ASan, and UBSan CTest suites Refs: #14 --- main.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main.cc b/main.cc index c71cae1..55e69f0 100644 --- a/main.cc +++ b/main.cc @@ -297,10 +297,11 @@ namespace { sqs.push_back(sq); pos = grid.next_pos(pos + idx); - idx = grid.largest_square(pos, n); // Have we reached the end? If so success! if (pos == grid.end()) { break; } + + idx = grid.largest_square(pos, n); } return {length, sqs}; -- 2.54.0