From f9a6895f9ed2f92f4368f7ee2f99836ce688849f Mon Sep 17 00:00:00 2001 From: "seer-by-sentry[bot]" <157164994+seer-by-sentry[bot]@users.noreply.github.com> Date: Sat, 18 Oct 2025 20:08:00 +0000 Subject: [PATCH] HTTPRequest: Prevent crashes during shutdown by skipping callbacks --- .../Include/GameNetwork/GeneralsOnline/HTTP/HTTPRequest.h | 4 ++-- .../GameNetwork/GeneralsOnline/HTTP/HTTPManager.cpp | 6 ++++-- .../GameNetwork/GeneralsOnline/HTTP/HTTPRequest.cpp | 8 ++++---- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/HTTP/HTTPRequest.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/HTTP/HTTPRequest.h index 1d0908e3564..2c2fbd92b0b 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/HTTP/HTTPRequest.h +++ b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/HTTP/HTTPRequest.h @@ -44,9 +44,9 @@ class HTTPRequest } } - void InvokeCallbackIfComplete(); + void InvokeCallbackIfComplete(bool bInvokeCallback = true); - void Threaded_SetComplete(CURLcode result); + void Threaded_SetComplete(CURLcode result, bool bInvokeCallback = true); // mainly used for downloads std::vector GetBuffer() { return m_vecBuffer; } diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/HTTP/HTTPManager.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/HTTP/HTTPManager.cpp index 2fe0faeed6b..9f020ed30b3 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/HTTP/HTTPManager.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/HTTP/HTTPManager.cpp @@ -91,7 +91,8 @@ void HTTPManager::Shutdown() HTTPRequest* pRequest = *it; if (pRequest != nullptr && pRequest->EasyHandleMatches(pCurlHandle)) { - pRequest->Threaded_SetComplete(m->data.result); + // Skip callbacks during shutdown to avoid use-after-free + pRequest->Threaded_SetComplete(m->data.result, false); delete pRequest; m_vecRequestsInFlight.erase(it); break; @@ -205,7 +206,8 @@ void HTTPManager::Tick() { if (pRequest != nullptr && pRequest->EasyHandleMatches(pCurlHandle)) { - pRequest->Threaded_SetComplete(m->data.result); + // Invoke callbacks during normal operation + pRequest->Threaded_SetComplete(m->data.result, true); vecItemsToRemove.push_back(pRequest); } } diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/HTTP/HTTPRequest.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/HTTP/HTTPRequest.cpp index dc06f283a1a..a364dbec270 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/HTTP/HTTPRequest.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/HTTP/HTTPRequest.cpp @@ -88,9 +88,9 @@ void HTTPRequest::OnResponsePartialWrite(std::uint8_t* pBuffer, size_t numBytes) InvokeProgressUpdateCallback(); } -void HTTPRequest::InvokeCallbackIfComplete() +void HTTPRequest::InvokeCallbackIfComplete(bool bInvokeCallback) { - if (m_bIsComplete) + if (m_bIsComplete && bInvokeCallback) { if (m_completionCallback != nullptr) { @@ -109,7 +109,7 @@ void HTTPRequest::InvokeCallbackIfComplete() } } -void HTTPRequest::Threaded_SetComplete(CURLcode result) +void HTTPRequest::Threaded_SetComplete(CURLcode result, bool bInvokeCallback) { // store response code curl_easy_getinfo(m_pCURL, CURLINFO_RESPONSE_CODE, &m_responseCode); @@ -148,7 +148,7 @@ void HTTPRequest::Threaded_SetComplete(CURLcode result) NetworkLog(ELogVerbosity::LOG_RELEASE, "[%p|%s] Response was %d - %s!", this, strURIRedacted.c_str(), m_responseCode, strResponse.c_str()); // trigger callback - InvokeCallbackIfComplete(); + InvokeCallbackIfComplete(bInvokeCallback); } void HTTPRequest::PlatformStartRequest()