From f0c238dbffed55ff2131b3f9027efd1bb7b0b0b3 Mon Sep 17 00:00:00 2001
From: Scott Pruett <spruett@fb.com>
Date: Fri, 26 Feb 2021 11:09:12 -0800
Subject: [PATCH] fix use-after-scope problems in BoundedAsyncPipeTest

Summary:
BoundedAsyncPipe::write() accepts arguments by-reference, so even
these constants may be out-of-scope by the time the coroutine actually runs,
causing use-after-scope problems which are detected by ASAN.

Wrapping in co_invoke allows us to scope the parameter so that it
lives long enough.

Reviewed By: lxfind

Differential Revision: D26649913

fbshipit-source-id: 5bc6b7f64a5e75c9386b245fa3fd1484efaf1d13
---
 folly/experimental/coro/test/AsyncPipeTest.cpp | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/folly/experimental/coro/test/AsyncPipeTest.cpp b/folly/experimental/coro/test/AsyncPipeTest.cpp
index 9fd598b4a..e7e2e612c 100644
--- a/folly/experimental/coro/test/AsyncPipeTest.cpp
+++ b/folly/experimental/coro/test/AsyncPipeTest.cpp
@@ -354,7 +354,14 @@ TEST(BoundedAsyncPipeTest, PublisherBlocks) {
       co_await pipe.write(i);
     }
 
-    auto writeFuture = pipe.write(20).scheduleOn(&executor).start();
+    // wrap in co_invoke() here, since write() accepts arguments by reference,
+    // and temporaries may go out of scope
+    auto writeFuture =
+        folly::coro::co_invoke([&pipe = pipe]() -> folly::coro::Task<bool> {
+          co_return co_await pipe.write(20);
+        })
+            .scheduleOn(&executor)
+            .start();
     executor.drain();
     EXPECT_FALSE(writeFuture.isReady());
 
@@ -378,7 +385,12 @@ TEST(BoundedAsyncPipeTest, BlockingPublisherCanceledOnDestroy) {
 
     std::vector<folly::SemiFuture<bool>> futures;
     for (size_t i = 0; i < 5; ++i) {
-      auto writeFuture = pipe.write(20).scheduleOn(&executor).start();
+      auto writeFuture =
+          folly::coro::co_invoke([&pipe = pipe]() -> folly::coro::Task<bool> {
+            co_return co_await pipe.write(20);
+          })
+              .scheduleOn(&executor)
+              .start();
       executor.drain();
       EXPECT_FALSE(writeFuture.isReady());
       futures.emplace_back(std::move(writeFuture));
-- 
2.26.2