From 3e2aabd0818cd9de536abbbb2a78769ea0289ce7 Mon Sep 17 00:00:00 2001 From: ldm0 Date: Tue, 3 Nov 2026 11:58:59 +0800 Subject: [PATCH] fix(curl): synchronize shared peer and credential references Protect counts shared by detached easy handles and cached connections with curl platform locks. Decide the last release under the same lock without holding it across allocation, destruction, or callbacks. --- vendor/curl-sys-0.4.91/curl/lib/creds.c | 12 ++--- .../curl-sys-0.4.91/curl/lib/moli_refcount.h | 46 +++++++++++++++++++ vendor/curl-sys-0.4.91/curl/lib/peer.c | 12 ++--- 3 files changed, 54 insertions(+), 16 deletions(-) create mode 100644 vendor/curl-sys-0.4.91/curl/lib/moli_refcount.h diff --git a/vendor/curl-sys-0.4.91/curl/lib/creds.c b/vendor/curl-sys-0.4.91/curl/lib/creds.c index 5507ae86f6..d5f700b8ed 100644 --- a/vendor/curl-sys-0.4.91/curl/lib/creds.c +++ b/vendor/curl-sys-0.4.91/curl/lib/creds.c @@ -29,6 +29,7 @@ #include "curl_trc.h" #include "strcase.h" #include "urldata.h" +#include "moli_refcount.h" CURLcode Curl_creds_create(const char *user, @@ -132,10 +133,8 @@ void Curl_creds_link(struct Curl_creds **pdest, struct Curl_creds *src) if(*pdest != src) { Curl_creds_unlink(pdest); *pdest = src; - if(src) { - DEBUGASSERT(src->refcount < UINT32_MAX); - src->refcount++; - } + if(src) + moli_refcount_link(&src->refcount); } } @@ -144,11 +143,8 @@ void Curl_creds_unlink(struct Curl_creds **pcreds) if(*pcreds) { struct Curl_creds *creds = *pcreds; - DEBUGASSERT(creds->refcount); *pcreds = NULL; - if(creds->refcount) - creds->refcount--; - if(!creds->refcount) { + if(moli_refcount_unlink(&creds->refcount)) { curlx_memzero(creds, sizeof(*creds) + creds->bufsize); curlx_free(creds); } diff --git a/vendor/curl-sys-0.4.91/curl/lib/moli_refcount.h b/vendor/curl-sys-0.4.91/curl/lib/moli_refcount.h new file mode 100644 index 0000000000..258bec8978 --- /dev/null +++ b/vendor/curl-sys-0.4.91/curl/lib/moli_refcount.h @@ -0,0 +1,46 @@ +#ifndef HEADER_CURL_MOLI_REFCOUNT_H +#define HEADER_CURL_MOLI_REFCOUNT_H +/* SPDX-License-Identifier: curl */ + +#include "easy_lock.h" + +/* A removed easy may be cleaned up while its former multi reuses a cached + * connection. Both retain peers and credentials. Protect their counts even + * though the application never uses the same easy from two threads. + * + * Each including translation unit owns one object family and its lock. Only + * the count is protected; no allocation, destruction or curl callbacks run + * under the lock. Use curl's existing platform lock and single-thread fallback. + */ +#ifdef GLOBAL_INIT_IS_THREADSAFE +static curl_simple_lock moli_refcount_lock = CURL_SIMPLE_LOCK_INIT; +#endif + +static CURL_INLINE void moli_refcount_link(uint32_t *count) +{ +#ifdef GLOBAL_INIT_IS_THREADSAFE + curl_simple_lock_lock(&moli_refcount_lock); +#endif + DEBUGASSERT(*count && *count < UINT32_MAX); + ++*count; +#ifdef GLOBAL_INIT_IS_THREADSAFE + curl_simple_lock_unlock(&moli_refcount_lock); +#endif +} + +static CURL_INLINE bool moli_refcount_unlink(uint32_t *count) +{ + bool last; +#ifdef GLOBAL_INIT_IS_THREADSAFE + curl_simple_lock_lock(&moli_refcount_lock); +#endif + DEBUGASSERT(*count); + last = !--*count; +#ifdef GLOBAL_INIT_IS_THREADSAFE + curl_simple_lock_unlock(&moli_refcount_lock); +#endif + /* Do not read the count again: another owner may already have freed it. */ + return last; +} + +#endif /* HEADER_CURL_MOLI_REFCOUNT_H */ diff --git a/vendor/curl-sys-0.4.91/curl/lib/peer.c b/vendor/curl-sys-0.4.91/curl/lib/peer.c index b5bf7b7334..9e588ffb02 100644 --- a/vendor/curl-sys-0.4.91/curl/lib/peer.c +++ b/vendor/curl-sys-0.4.91/curl/lib/peer.c @@ -76,6 +76,7 @@ #include "url.h" #include "urlapi-int.h" #include "vtls/vtls.h" +#include "moli_refcount.h" struct peer_parse { const struct Curl_scheme *scheme; @@ -296,10 +297,8 @@ void Curl_peer_link(struct Curl_peer **pdest, struct Curl_peer *src) if(*pdest != src) { Curl_peer_unlink(pdest); *pdest = src; - if(src) { - DEBUGASSERT(src->refcount < UINT32_MAX); - src->refcount++; - } + if(src) + moli_refcount_link(&src->refcount); } } @@ -308,11 +307,8 @@ void Curl_peer_unlink(struct Curl_peer **ppeer) if(*ppeer) { struct Curl_peer *peer = *ppeer; - DEBUGASSERT(peer->refcount); *ppeer = NULL; - if(peer->refcount) - peer->refcount--; - if(!peer->refcount) { + if(moli_refcount_unlink(&peer->refcount)) { curlx_free(peer); } }