From 4f33bcbb3e1eee2876c9634196761f22e1b331dd Mon Sep 17 00:00:00 2001 From: Kefu Chai Date: Fri, 9 Jan 2026 09:32:49 +0800 Subject: [PATCH] test/mds: fix stack-use-after-scope in unittest_mds_quiesce_db The cartesian_apply() function in TestQuiesceDb.cc had a stack-use- after-scope issue detected by ASan. The problem was that the lambda function at line 513 had an implicit return type deduction that returned a value instead of a reference: auto f = [&q](const auto &args) { q = div(q.quot, args.size()); return args.at(q.rem); // Returns V instead of V const& }; Even though args.at(q.rem) returns a const reference to an element in the array, the lambda's auto return type deduction caused it to return by value. This meant the tuple at line 518: auto apply_tuple = std::tuple { f(array_args)... }; was storing references to temporary values that went out of scope immediately after tuple construction. When std::apply() later tried to use these references, it accessed freed stack memory. Fix by explicitly specifying the lambda's return type as decltype(auto) to preserve the reference semantics: auto f = [&q](const auto &args) -> decltype(auto) { q = div(q.quot, args.size()); return args.at(q.rem); // Now returns V const& as intended }; This ensures the lambda returns a reference to the array element, which remains valid for the lifetime of array_args (the entire scope of cartesian_apply()). This preserves the original optimization of avoiding copies while fixing the use-after-scope issue. Signed-off-by: Kefu Chai --- src/test/mds/TestQuiesceDb.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/test/mds/TestQuiesceDb.cc b/src/test/mds/TestQuiesceDb.cc index 7f416e2aaa8..d589da5a541 100644 --- a/src/test/mds/TestQuiesceDb.cc +++ b/src/test/mds/TestQuiesceDb.cc @@ -510,14 +510,15 @@ void cartesian_apply(F func, std::array const & ... array_args) { // we use parameter pack expansion as part of the brace initializer // to perform sequential calculation of the - auto f = [&q](const auto &args) { + // Lambda returns reference to avoid copying and ensure lifetime validity + auto f = [&q](const auto &args) -> decltype(auto) { q = div(q.quot, args.size()); return args.at(q.rem); }; - auto apply_tuple = std::tuple { + auto apply_tuple = std::tuple { f(array_args) - ... + ... }; if (!std::apply(func, apply_tuple)) { -- 2.47.3