From: Kefu Chai Date: Fri, 9 Jan 2026 01:32:49 +0000 (+0800) Subject: test/mds: fix stack-use-after-scope in unittest_mds_quiesce_db X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=4f33bcbb3e1eee2876c9634196761f22e1b331dd;p=ceph.git 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 --- diff --git a/src/test/mds/TestQuiesceDb.cc b/src/test/mds/TestQuiesceDb.cc index 7f416e2aaa83..d589da5a5415 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)) {