Skip to content

Commit 0a1e92a

Browse files
authored
test: fix heap use-after-free in ~IntegrationTestServer. (envoyproxy#4319)
When the server thread exits independently of the main test thread (e.g. exception catch), we could race on the access to the server admin port via server_. We latch this in this PR to avoid unsafe behavior. We might still have a stale address, but the request should then fail or timeout. Fixes oss-fuzz issues https://oss-fuzz.com/v2/testcase-detail/5719024990683136 and https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10027. Risk level: Low Testing: TSAN integration tests. Signed-off-by: Harvey Tuch <[email protected]>
1 parent cddc732 commit 0a1e92a

File tree

2 files changed

+11
-5
lines changed

2 files changed

+11
-5
lines changed

test/integration/server.cc

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,12 @@ void IntegrationTestServer::start(const Network::Address::IpVersion version,
5858
IntegrationTestServer::~IntegrationTestServer() {
5959
ENVOY_LOG(info, "stopping integration test server");
6060

61-
BufferingStreamDecoderPtr response =
62-
IntegrationUtil::makeSingleRequest(server_->admin().socket().localAddress(), "POST",
63-
"/quitquitquit", "", Http::CodecClient::Type::HTTP1);
64-
EXPECT_TRUE(response->complete());
65-
EXPECT_STREQ("200", response->headers().Status()->value().c_str());
61+
if (admin_address_ != nullptr) {
62+
BufferingStreamDecoderPtr response = IntegrationUtil::makeSingleRequest(
63+
admin_address_, "POST", "/quitquitquit", "", Http::CodecClient::Type::HTTP1);
64+
EXPECT_TRUE(response->complete());
65+
EXPECT_STREQ("200", response->headers().Status()->value().c_str());
66+
}
6667

6768
thread_->join();
6869
}
@@ -107,6 +108,10 @@ void IntegrationTestServer::threadRoutine(const Network::Address::IpVersion vers
107108
restarter, stats_store, lock, *this, std::move(random_generator), tls));
108109
pending_listeners_ = server_->listenerManager().listeners().size();
109110
ENVOY_LOG(info, "waiting for {} test server listeners", pending_listeners_);
111+
// This is technically thread unsafe (assigning to a shared_ptr accessed
112+
// across threads), but because we synchronize below on server_set, the only
113+
// consumer on the main test thread in ~IntegrationTestServer will not race.
114+
admin_address_ = server_->admin().socket().localAddress();
110115
server_set_.setReady();
111116
server_->run();
112117
server_.reset();

test/integration/server.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ class IntegrationTestServer : Logger::Loggable<Logger::Id::testing>,
309309
Stats::Store* stat_store_{};
310310
std::function<void()> on_worker_listener_added_cb_;
311311
std::function<void()> on_worker_listener_removed_cb_;
312+
Network::Address::InstanceConstSharedPtr admin_address_;
312313
};
313314

314315
} // namespace Envoy

0 commit comments

Comments
 (0)