From 4473e39efc211b72e8a407e0c5987efa8df7a98b Mon Sep 17 00:00:00 2001 From: Marcel Walter Date: Sat, 8 Aug 2026 08:43:10 +0200 Subject: [PATCH] acd: seed bestPerm to avoid an uninitialised read in enumerate_iset_combinations bestPerm is only written inside the 'cost < best_cost' branch. When no combination beats the initial best_cost -- which happens for an infeasible free-set size -- the array is never written, yet the tail of the function still evaluates permutations[bestPerm[i]]. That reads uninitialised stack and then uses the value to index permutations[], so it is an out-of-bounds read as well. Upstream results are unaffected in practice because the caller discards the permutation on that path, but it is undefined behaviour and it becomes a hard segfault as soon as the stack layout changes -- adding two members to the decomposer object was enough to trigger it reliably. Seeding the identity permutation in the existing initialisation loop is sufficient and costs nothing. --- src/map/if/acd/ac_decomposition.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/map/if/acd/ac_decomposition.hpp b/src/map/if/acd/ac_decomposition.hpp index 8d5ddb5c43..c6df54662e 100644 --- a/src/map/if/acd/ac_decomposition.hpp +++ b/src/map/if/acd/ac_decomposition.hpp @@ -482,6 +482,11 @@ class ac_decomposition_impl for ( uint32_t i = 0; i < num_vars; ++i ) { pComb[i] = pInvPerm[i] = i; + /* bestPerm is written only when some combination beats the initial + * best_cost. When none does, the loop below still evaluates + * permutations[bestPerm[i]], which reads uninitialised stack and then + * indexes permutations[] with it. Seed the identity permutation. */ + bestPerm[i] = i; } /* early bail-out conditions */