Skip to content

Commit f46df5b

Browse files
committed
Fix use of dangling references
When the resolve thread is detached, local variables were still used, which could lead to a program crash.
1 parent 89c932f commit f46df5b

File tree

1 file changed

+36
-16
lines changed

1 file changed

+36
-16
lines changed

httplib.h

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3798,31 +3798,51 @@ inline int getaddrinfo_with_timeout(const char *node, const char *service,
37983798
}
37993799
#else
38003800
// Fallback implementation using thread-based timeout for other Unix systems
3801-
std::mutex result_mutex;
3802-
std::condition_variable result_cv;
3803-
auto completed = false;
3804-
auto result = EAI_SYSTEM;
3805-
struct addrinfo *result_addrinfo = nullptr;
38063801

3807-
std::thread resolve_thread([&]() {
3808-
auto thread_result = getaddrinfo(node, service, hints, &result_addrinfo);
3802+
struct GetAddrInfoState {
3803+
std::mutex mutex{};
3804+
std::condition_variable result_cv;
3805+
bool completed{false};
3806+
int result{0};
3807+
std::string node{};
3808+
std::string service{};
3809+
struct addrinfo hints {};
3810+
struct addrinfo *info{nullptr};
3811+
};
38093812

3810-
std::lock_guard<std::mutex> lock(result_mutex);
3811-
result = thread_result;
3812-
completed = true;
3813-
result_cv.notify_one();
3813+
// Allocate on the heap, so the resolver thread can keep using the data.
3814+
auto state = std::make_shared<GetAddrInfoState>();
3815+
3816+
state->result = EAI_SYSTEM;
3817+
state->node = node;
3818+
state->service = service;
3819+
state->hints.ai_flags = hints->ai_flags;
3820+
state->hints.ai_family = hints->ai_family;
3821+
state->hints.ai_socktype = hints->ai_socktype;
3822+
state->hints.ai_protocol = hints->ai_protocol;
3823+
// The remaining fields of "hints" must be zeroed, so do not copy them.
3824+
3825+
std::thread resolve_thread([=]() {
3826+
auto thread_result = getaddrinfo(
3827+
state->node.c_str(), state->service.c_str(), hints, &state->info);
3828+
3829+
std::lock_guard<std::mutex> lock(state->mutex);
3830+
state->result = thread_result;
3831+
state->completed = true;
3832+
state->result_cv.notify_one();
38143833
});
38153834

38163835
// Wait for completion or timeout
3817-
std::unique_lock<std::mutex> lock(result_mutex);
3818-
auto finished = result_cv.wait_for(lock, std::chrono::seconds(timeout_sec),
3819-
[&] { return completed; });
3836+
std::unique_lock<std::mutex> lock(state->mutex);
3837+
auto finished =
3838+
state->result_cv.wait_for(lock, std::chrono::seconds(timeout_sec),
3839+
[&] { return state->completed; });
38203840

38213841
if (finished) {
38223842
// Operation completed within timeout
38233843
resolve_thread.join();
3824-
*res = result_addrinfo;
3825-
return result;
3844+
*res = state->info;
3845+
return state->result;
38263846
} else {
38273847
// Timeout occurred
38283848
resolve_thread.detach(); // Let the thread finish in background

0 commit comments

Comments
 (0)