[ntcore] Fix use-after-free on connection termination (#7177)

The stream can close (e.g. due to an error) while in the middle of writing. The close callback would immediately destroy the connection object, resulting in the writing code having a use-after-free. Fix this by deferring the deletion to the loop main using a single-shot timer.
This commit is contained in:
Peter Johnson
2024-10-10 23:03:55 -06:00
committed by GitHub
parent a71cee1112
commit 0cfff31439
3 changed files with 6 additions and 5 deletions

View File

@@ -125,7 +125,9 @@ void NetworkServer::ServerConnection::UpdateOutgoingTimer(uint32_t repeatMs) {
void NetworkServer::ServerConnection::ConnectionClosed() {
// don't call back into m_server if it's being destroyed
if (!m_outgoingTimer->IsLoopClosing()) {
m_server.m_serverImpl.RemoveClient(m_clientId);
uv::Timer::SingleShot(m_outgoingTimer->GetLoopRef(), uv::Timer::Time{0},
[client = m_server.m_serverImpl.RemoveClient(
m_clientId)]() mutable { client.reset(); });
m_server.RemoveConnection(this);
}
m_outgoingTimer->Close();

View File

@@ -1252,7 +1252,7 @@ int ServerImpl::AddClient3(std::string_view connInfo, bool local,
return index;
}
void ServerImpl::RemoveClient(int clientId) {
std::shared_ptr<void> ServerImpl::RemoveClient(int clientId) {
DEBUG3("RemoveClient({})", clientId);
auto& client = m_clients[clientId];
@@ -1288,8 +1288,7 @@ void ServerImpl::RemoveClient(int clientId) {
DeleteTopic(client->m_metaPub);
DeleteTopic(client->m_metaSub);
// delete the client
client.reset();
return std::move(client);
}
bool ServerImpl::PersistentChanged() {

View File

@@ -80,7 +80,7 @@ class ServerImpl final {
int AddClient3(std::string_view connInfo, bool local,
net3::WireConnection3& wire, Connected3Func connected,
SetPeriodicFunc setPeriodic);
void RemoveClient(int clientId);
std::shared_ptr<void> RemoveClient(int clientId);
void ConnectionsChanged(const std::vector<ConnectionInfo>& conns);