]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
test/mds: fix stack-use-after-scope in unittest_mds_quiesce_db 66851/head
authorKefu Chai <k.chai@proxmox.com>
Fri, 9 Jan 2026 01:32:49 +0000 (09:32 +0800)
committerKefu Chai <k.chai@proxmox.com>
Fri, 9 Jan 2026 04:04:15 +0000 (12:04 +0800)
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<V const &...> { 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 <k.chai@proxmox.com>
src/test/mds/TestQuiesceDb.cc

index 7f416e2aaa8307bf7eca1216b2275b4e930bb206..d589da5a5415701e10d8eec9e3b66ff1d42ec3b9 100644 (file)
@@ -510,14 +510,15 @@ void cartesian_apply(F func, std::array<V, S> 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<V const &...> { 
+    auto apply_tuple = std::tuple<V const &...> {
       f(array_args)
-      ... 
+      ...
     };
 
     if (!std::apply(func, apply_tuple)) {