← Commit list

ffdbc04c7b

Stefan Eissing
Stefan Eissing
2026-02-02
SUCCESS Duration: 342s

Subject

hostip.c: fix leak of addrinfo

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

—

Build Log

(log yok)

Commit Diff GitHub →

lib/asyn-ares.c+1 -2
@@ -332,14 +332,13 @@ CURLcode Curl_async_is_resolved(struct Curl_easy *data,
result = ares->result;
if(ares->ares_status == ARES_SUCCESS && !result) {
data->state.async.dns =
- Curl_dnscache_mk_entry(data, ares->temp_ai,
+ Curl_dnscache_mk_entry(data, &ares->temp_ai,
data->state.async.hostname, 0,
data->state.async.port, FALSE);
if(!data->state.async.dns) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
- ares->temp_ai = NULL; /* temp_ai now owned by entry */
#ifdef HTTPSRR_WORKS
{
struct Curl_https_rrinfo *lhrr = Curl_httpsrr_dup_move(&ares->hinfo);
lib/asyn-thrdd.c+1 -2
@@ -604,10 +604,9 @@ CURLcode Curl_async_is_resolved(struct Curl_easy *data,
if(thrdd->addr->res) {
data->state.async.dns =
- Curl_dnscache_mk_entry(data, thrdd->addr->res,
+ Curl_dnscache_mk_entry(data, &thrdd->addr->res,
data->state.async.hostname, 0,
data->state.async.port, FALSE);
- thrdd->addr->res = NULL;
if(!data->state.async.dns)
result = CURLE_OUT_OF_MEMORY;
lib/doh.c+2 -3
@@ -1253,7 +1253,8 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
goto error;
/* we got a response, create a dns entry. */
- dns = Curl_dnscache_mk_entry(data, ai, dohp->host, 0, dohp->port, FALSE);
+ dns = Curl_dnscache_mk_entry(data, &ai, dohp->host, 0,
+ dohp->port, FALSE);
if(dns) {
/* Now add and HTTPSRR information if we have */
#ifdef USE_HTTPSRR
@@ -1278,8 +1279,6 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
result = Curl_dnscache_add(data, dns);
*dnsp = data->state.async.dns;
}
- else
- Curl_freeaddrinfo(ai);
} /* address processing done */
/* All done */
lib/hostip.c+17 -18
@@ -559,20 +559,20 @@ UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
struct Curl_dns_entry *
Curl_dnscache_mk_entry(struct Curl_easy *data,
- struct Curl_addrinfo *addr,
+ struct Curl_addrinfo **paddr,
const char *hostname,
size_t hostlen, /* length or zero */
int port,
bool permanent)
{
- struct Curl_dns_entry *dns;
+ struct Curl_dns_entry *dns = NULL;
#ifndef CURL_DISABLE_SHUFFLE_DNS
/* shuffle addresses if requested */
- if(data->set.dns_shuffle_addresses) {
- CURLcode result = Curl_shuffle_addr(data, &addr);
+ if(data->set.dns_shuffle_addresses && paddr) {
+ CURLcode result = Curl_shuffle_addr(data, paddr);
if(result)
- return NULL;
+ goto out;
}
#else
(void)data;
@@ -583,10 +583,10 @@ Curl_dnscache_mk_entry(struct Curl_easy *data,
/* Create a new cache entry */
dns = curlx_calloc(1, sizeof(struct Curl_dns_entry) + hostlen);
if(!dns)
- return NULL;
+ goto out;
dns->refcount = 1; /* the cache has the first reference */
- dns->addr = addr; /* this is the address(es) */
+ dns->addr = paddr ? *paddr : NULL; /* this is the address(es) */
if(permanent) {
dns->timestamp.tv_sec = 0; /* an entry that never goes stale */
dns->timestamp.tv_usec = 0; /* an entry that never goes stale */
@@ -598,13 +598,19 @@ Curl_dnscache_mk_entry(struct Curl_easy *data,
if(hostlen)
memcpy(dns->hostname, hostname, hostlen);
+out:
+ if(paddr) {
+ if(!dns)
+ Curl_freeaddrinfo(*paddr);
+ *paddr = NULL;
+ }
return dns;
}
static struct Curl_dns_entry *
dnscache_add_addr(struct Curl_easy *data,
struct Curl_dnscache *dnscache,
- struct Curl_addrinfo *addr,
+ struct Curl_addrinfo **paddr,
const char *hostname,
size_t hlen, /* length or zero */
int port,
@@ -615,7 +621,7 @@ dnscache_add_addr(struct Curl_easy *data,
struct Curl_dns_entry *dns;
struct Curl_dns_entry *dns2;
- dns = Curl_dnscache_mk_entry(data, addr, hostname, hlen, port, permanent);
+ dns = Curl_dnscache_mk_entry(data, paddr, hostname, hlen, port, permanent);
if(!dns)
return NULL;
@@ -627,7 +633,6 @@ dnscache_add_addr(struct Curl_easy *data,
dns2 = Curl_hash_add(&dnscache->entries, entry_id, entry_len + 1,
(void *)dns);
if(!dns2) {
- dns->addr = NULL;
dnscache_entry_free(dns);
return NULL;
}
@@ -977,13 +982,9 @@ out:
}
else if(addr) {
/* we got a response, create a dns entry, add to cache, return */
- dns = Curl_dnscache_mk_entry(data, addr, hostname, 0, port, FALSE);
+ dns = Curl_dnscache_mk_entry(data, &addr, hostname, 0, port, FALSE);
if(!dns || Curl_dnscache_add(data, dns)) {
/* this is OOM or similar, do not store such negative resolves */
- Curl_freeaddrinfo(addr);
- if(dns)
- /* avoid a dangling pointer to addr in the dying dns entry */
- dns->addr = NULL;
result = CURLE_OUT_OF_MEMORY;
goto error;
}
@@ -1442,14 +1443,12 @@ err:
}
/* put this new host in the cache */
- dns = dnscache_add_addr(data, dnscache, head, curlx_str(&source),
+ dns = dnscache_add_addr(data, dnscache, &head, curlx_str(&source),
curlx_strlen(&source), (int)port, permanent);
if(dns)
/* release the returned reference; the cache itself will keep the
* entry alive: */
dns->refcount--;
- else
- Curl_freeaddrinfo(head);
dnscache_unlock(data, dnscache);
lib/hostip.h+3 -2
@@ -151,13 +151,14 @@ void Curl_printable_address(const struct Curl_addrinfo *ip,
* The entry is created with a reference count of 1.
* Use `Curl_resolv_unlink()` to release your hold on it.
*
- * The call takes ownership of `addr`and makes a copy of `hostname`.
+ * The call takes ownership of `addr`, even in case of failure, and always
+ * clears `*paddr`. It makes a copy of `hostname`.
*
* Returns entry or NULL on OOM.
*/
struct Curl_dns_entry *
Curl_dnscache_mk_entry(struct Curl_easy *data,
- struct Curl_addrinfo *addr,
+ struct Curl_addrinfo **paddr,
const char *hostname,
size_t hostlen, /* length or zero */
int port,