hostip: make more functions return CURLcode

- Curl_async_getaddrinfo() always returned NULL so it was pointless.
  Return proper curlcode instead to distinguish between errors. Same for
  Curl_doh().
- simplify the IP address handling
- make Curl_str2addr() function return CURLcode

Closes #19669
This commit is contained in:
Daniel Stenberg 2025-11-24 14:00:09 +01:00
parent a075d1c0d8
commit ce06fe7771
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
9 changed files with 117 additions and 145 deletions

View file

@ -718,25 +718,18 @@ static void async_ares_rr_done(void *user_data, ares_status_t status,
/* /*
* Curl_async_getaddrinfo() - when using ares * Curl_async_getaddrinfo() - when using ares
* *
* Returns name information about the given hostname and port number. If * Starts a name resolve for the given hostname and port number.
* successful, the 'hostent' is returned and the fourth argument will point to
* memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else.
*/ */
struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data, CURLcode Curl_async_getaddrinfo(struct Curl_easy *data, const char *hostname,
const char *hostname, int port, int ip_version)
int port,
int ip_version,
int *waitp)
{ {
struct async_ares_ctx *ares = &data->state.async.ares; struct async_ares_ctx *ares = &data->state.async.ares;
#ifdef USE_HTTPSRR #ifdef USE_HTTPSRR
char *rrname = NULL; char *rrname = NULL;
#endif #endif
*waitp = 0; /* default to synchronous response */
if(async_ares_init_lazy(data)) if(async_ares_init_lazy(data))
return NULL; return CURLE_FAILED_INIT;
data->state.async.done = FALSE; /* not done */ data->state.async.done = FALSE; /* not done */
data->state.async.dns = NULL; /* clear */ data->state.async.dns = NULL; /* clear */
@ -744,12 +737,12 @@ struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data,
data->state.async.ip_version = ip_version; data->state.async.ip_version = ip_version;
data->state.async.hostname = strdup(hostname); data->state.async.hostname = strdup(hostname);
if(!data->state.async.hostname) if(!data->state.async.hostname)
return NULL; return CURLE_OUT_OF_MEMORY;
#ifdef USE_HTTPSRR #ifdef USE_HTTPSRR
if(port != 443) { if(port != 443) {
rrname = curl_maprintf("_%d_.https.%s", port, hostname); rrname = curl_maprintf("_%d_.https.%s", port, hostname);
if(!rrname) if(!rrname)
return NULL; return CURLE_OUT_OF_MEMORY;
} }
#endif #endif
@ -836,9 +829,8 @@ struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data,
async_ares_rr_done, data, NULL); async_ares_rr_done, data, NULL);
} }
#endif #endif
*waitp = 1; /* expect asynchronous response */
return NULL; /* no struct yet */ return CURLE_OK;
} }
/* Set what DNS server are is to use. This is called in 2 situations: /* Set what DNS server are is to use. This is called in 2 situations:

View file

@ -755,15 +755,11 @@ struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data,
/* /*
* Curl_async_getaddrinfo() - for getaddrinfo * Curl_async_getaddrinfo() - for getaddrinfo
*/ */
struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data, CURLcode Curl_async_getaddrinfo(struct Curl_easy *data, const char *hostname,
const char *hostname, int port, int ip_version)
int port,
int ip_version,
int *waitp)
{ {
struct addrinfo hints; struct addrinfo hints;
int pf = PF_INET; int pf = PF_INET;
*waitp = 0; /* default to synchronous response */
CURL_TRC_DNS(data, "init threaded resolve of %s:%d", hostname, port); CURL_TRC_DNS(data, "init threaded resolve of %s:%d", hostname, port);
#ifdef CURLRES_IPV6 #ifdef CURLRES_IPV6
@ -785,14 +781,11 @@ struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data,
SOCK_STREAM : SOCK_DGRAM; SOCK_STREAM : SOCK_DGRAM;
/* fire up a new resolver thread! */ /* fire up a new resolver thread! */
if(async_thrdd_init(data, hostname, port, ip_version, &hints)) { if(async_thrdd_init(data, hostname, port, ip_version, &hints))
*waitp = 1; /* expect asynchronous response */ return CURLE_OK;
return NULL;
}
failf(data, "getaddrinfo() thread failed to start"); failf(data, "getaddrinfo() thread failed to start");
return NULL; return CURLE_FAILED_INIT;
} }
#endif /* !HAVE_GETADDRINFO */ #endif /* !HAVE_GETADDRINFO */

View file

@ -118,11 +118,8 @@ CURLcode Curl_async_await(struct Curl_easy *data,
* Each resolver backend must of course make sure to return data in the * Each resolver backend must of course make sure to return data in the
* correct format to comply with this. * correct format to comply with this.
*/ */
struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data, CURLcode Curl_async_getaddrinfo(struct Curl_easy *data, const char *hostname,
const char *hostname, int port, int ip_version);
int port,
int ip_version,
int *waitp);
#ifdef USE_ARES #ifdef USE_ARES
/* common functions for c-ares and threaded resolver with HTTPSRR */ /* common functions for c-ares and threaded resolver with HTTPSRR */

View file

@ -347,7 +347,7 @@ Curl_he2ai(const struct hostent *he, int port)
#endif #endif
/* /*
* Curl_ip2addr() * ip2addr()
* *
* This function takes an Internet address, in binary form, as input parameter * This function takes an Internet address, in binary form, as input parameter
* along with its address family and the string version of the address, and it * along with its address family and the string version of the address, and it
@ -355,8 +355,9 @@ Curl_he2ai(const struct hostent *he, int port)
* given address/host * given address/host
*/ */
struct Curl_addrinfo * static CURLcode
Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port) ip2addr(struct Curl_addrinfo **addrp,
int af, const void *inaddr, const char *hostname, int port)
{ {
struct Curl_addrinfo *ai; struct Curl_addrinfo *ai;
size_t addrsize; size_t addrsize;
@ -369,6 +370,7 @@ Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port)
DEBUGASSERT(inaddr && hostname); DEBUGASSERT(inaddr && hostname);
namelen = strlen(hostname) + 1; namelen = strlen(hostname) + 1;
*addrp = NULL;
if(af == AF_INET) if(af == AF_INET)
addrsize = sizeof(struct sockaddr_in); addrsize = sizeof(struct sockaddr_in);
@ -377,12 +379,12 @@ Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port)
addrsize = sizeof(struct sockaddr_in6); addrsize = sizeof(struct sockaddr_in6);
#endif #endif
else else
return NULL; return CURLE_BAD_FUNCTION_ARGUMENT;
/* allocate memory to hold the struct, the address and the name */ /* allocate memory to hold the struct, the address and the name */
ai = calloc(1, sizeof(struct Curl_addrinfo) + addrsize + namelen); ai = calloc(1, sizeof(struct Curl_addrinfo) + addrsize + namelen);
if(!ai) if(!ai)
return NULL; return CURLE_OUT_OF_MEMORY;
/* put the address after the struct */ /* put the address after the struct */
ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo)); ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo));
/* then put the name after the address */ /* then put the name after the address */
@ -412,29 +414,46 @@ Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port)
break; break;
#endif #endif
} }
*addrp = ai;
return ai; return CURLE_OK;
} }
/* /*
* Given an IPv4 or IPv6 dotted string address, this converts it to a proper * Given an IPv4 or IPv6 dotted string address, this converts it to a proper
* allocated Curl_addrinfo struct and returns it. * allocated Curl_addrinfo struct and returns it.
*/ */
struct Curl_addrinfo *Curl_str2addr(char *address, int port) CURLcode Curl_str2addr(const char *address, int port,
struct Curl_addrinfo **addrp)
{ {
struct in_addr in; struct in_addr in;
if(curlx_inet_pton(AF_INET, address, &in) > 0) if(curlx_inet_pton(AF_INET, address, &in) > 0)
/* This is a dotted IP address 123.123.123.123-style */ /* This is a dotted IP address 123.123.123.123-style */
return Curl_ip2addr(AF_INET, &in, address, port); return ip2addr(addrp, AF_INET, &in, address, port);
#ifdef USE_IPV6 #ifdef USE_IPV6
{ {
struct in6_addr in6; struct in6_addr in6;
if(curlx_inet_pton(AF_INET6, address, &in6) > 0) if(curlx_inet_pton(AF_INET6, address, &in6) > 0)
/* This is a dotted IPv6 address ::1-style */ /* This is a dotted IPv6 address ::1-style */
return Curl_ip2addr(AF_INET6, &in6, address, port); return ip2addr(addrp, AF_INET6, &in6, address, port);
} }
#endif #endif
return NULL; /* bad input format */ return CURLE_BAD_FUNCTION_ARGUMENT; /* bad input format */
}
bool Curl_is_ipaddr(const char *address)
{
struct in_addr in;
if(curlx_inet_pton(AF_INET, address, &in) > 0)
return TRUE;
#ifdef USE_IPV6
{
struct in6_addr in6;
if(curlx_inet_pton(AF_INET6, address, &in6) > 0)
/* This is a dotted IPv6 address ::1-style */
return TRUE;
}
#endif
return FALSE;
} }
#ifdef USE_UNIX_SOCKETS #ifdef USE_UNIX_SOCKETS

View file

@ -76,10 +76,8 @@ struct Curl_addrinfo *
Curl_he2ai(const struct hostent *he, int port); Curl_he2ai(const struct hostent *he, int port);
#endif #endif
struct Curl_addrinfo * bool Curl_is_ipaddr(const char *address);
Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port); CURLcode Curl_str2addr(const char *dotted, int port, struct Curl_addrinfo **);
struct Curl_addrinfo *Curl_str2addr(char *dotted, int port);
#ifdef USE_UNIX_SOCKETS #ifdef USE_UNIX_SOCKETS
struct Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, struct Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath,

View file

@ -441,15 +441,12 @@ error:
} }
/* /*
* Curl_doh() resolves a name using DoH. It resolves a name and returns a * Curl_doh() starts a name resolve using DoH. It resolves a name and returns
* 'Curl_addrinfo *' with the address information. * a 'Curl_addrinfo *' with the address information.
*/ */
struct Curl_addrinfo *Curl_doh(struct Curl_easy *data, CURLcode Curl_doh(struct Curl_easy *data, const char *hostname,
const char *hostname, int port, int ip_version)
int port,
int ip_version,
int *waitp)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct doh_probes *dohp = NULL; struct doh_probes *dohp = NULL;
@ -467,12 +464,12 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
data->state.async.ip_version = ip_version; data->state.async.ip_version = ip_version;
data->state.async.hostname = strdup(hostname); data->state.async.hostname = strdup(hostname);
if(!data->state.async.hostname) if(!data->state.async.hostname)
return NULL; return CURLE_OUT_OF_MEMORY;
/* start clean, consider allocating this struct on demand */ /* start clean, consider allocating this struct on demand */
data->state.async.doh = dohp = calloc(1, sizeof(struct doh_probes)); data->state.async.doh = dohp = calloc(1, sizeof(struct doh_probes));
if(!dohp) if(!dohp)
return NULL; return CURLE_OUT_OF_MEMORY;
for(i = 0; i < DOH_SLOT_COUNT; ++i) { for(i = 0; i < DOH_SLOT_COUNT; ++i) {
dohp->probe_resp[i].probe_mid = UINT_MAX; dohp->probe_resp[i].probe_mid = UINT_MAX;
@ -527,12 +524,11 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
dohp->pending++; dohp->pending++;
} }
#endif #endif
*waitp = TRUE; /* this never returns synchronously */ return CURLE_OK;
return NULL;
error: error:
Curl_doh_cleanup(data); Curl_doh_cleanup(data);
return NULL; return result;
} }
static DOHcode doh_skipqname(const unsigned char *doh, size_t dohlen, static DOHcode doh_skipqname(const unsigned char *doh, size_t dohlen,
@ -1300,6 +1296,8 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
result = Curl_dnscache_add(data, dns); result = Curl_dnscache_add(data, dns);
*dnsp = data->state.async.dns; *dnsp = data->state.async.dns;
} }
else
Curl_freeaddrinfo(ai);
} /* address processing done */ } /* address processing done */
/* All done */ /* All done */

View file

@ -112,15 +112,12 @@ struct doh_probes {
}; };
/* /*
* Curl_doh() resolve a name using DoH (DNS-over-HTTPS). It resolves a name * Curl_doh() starts a name resolve using DoH (DNS-over-HTTPS). It resolves a
* and returns a 'Curl_addrinfo *' with the address information. * name and returns a 'Curl_addrinfo *' with the address information.
*/ */
struct Curl_addrinfo *Curl_doh(struct Curl_easy *data, CURLcode Curl_doh(struct Curl_easy *data, const char *hostname,
const char *hostname, int port, int ip_version);
int port,
int ip_version,
int *waitp);
CURLcode Curl_doh_is_resolved(struct Curl_easy *data, CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dns); struct Curl_dns_entry **dns);

View file

@ -509,10 +509,8 @@ Curl_dnscache_mk_entry(struct Curl_easy *data,
/* shuffle addresses if requested */ /* shuffle addresses if requested */
if(data->set.dns_shuffle_addresses) { if(data->set.dns_shuffle_addresses) {
CURLcode result = Curl_shuffle_addr(data, &addr); CURLcode result = Curl_shuffle_addr(data, &addr);
if(result) { if(result)
Curl_freeaddrinfo(addr);
return NULL; return NULL;
}
} }
#else #else
(void)data; (void)data;
@ -522,10 +520,8 @@ Curl_dnscache_mk_entry(struct Curl_easy *data,
/* Create a new cache entry */ /* Create a new cache entry */
dns = calloc(1, sizeof(struct Curl_dns_entry) + hostlen); dns = calloc(1, sizeof(struct Curl_dns_entry) + hostlen);
if(!dns) { if(!dns)
Curl_freeaddrinfo(addr);
return NULL; return NULL;
}
dns->refcount = 1; /* the cache has the first reference */ dns->refcount = 1; /* the cache has the first reference */
dns->addr = addr; /* this is the address(es) */ dns->addr = addr; /* this is the address(es) */
@ -569,6 +565,7 @@ dnscache_add_addr(struct Curl_easy *data,
dns2 = Curl_hash_add(&dnscache->entries, entry_id, entry_len + 1, dns2 = Curl_hash_add(&dnscache->entries, entry_id, entry_len + 1,
(void *)dns); (void *)dns);
if(!dns2) { if(!dns2) {
dns->addr = NULL;
dnscache_entry_free(dns); dnscache_entry_free(dns);
return NULL; return NULL;
} }
@ -744,40 +741,6 @@ static bool tailmatch(const char *full, size_t flen,
return curl_strnequal(part, &full[flen - plen], plen); return curl_strnequal(part, &full[flen - plen], plen);
} }
static struct Curl_addrinfo *
convert_ipaddr_direct(const char *hostname, int port, bool *is_ipaddr)
{
struct in_addr in;
*is_ipaddr = FALSE;
/* First check if this is an IPv4 address string */
if(curlx_inet_pton(AF_INET, hostname, &in) > 0) {
/* This is a dotted IP address 123.123.123.123-style */
*is_ipaddr = TRUE;
#ifdef USE_RESOLVE_ON_IPS
(void)port;
return NULL;
#else
return Curl_ip2addr(AF_INET, &in, hostname, port);
#endif
}
#ifdef USE_IPV6
else {
struct in6_addr in6;
/* check if this is an IPv6 address string */
if(curlx_inet_pton(AF_INET6, hostname, &in6) > 0) {
/* This is an IPv6 address literal */
*is_ipaddr = TRUE;
#ifdef USE_RESOLVE_ON_IPS
return NULL;
#else
return Curl_ip2addr(AF_INET6, &in6, hostname, port);
#endif
}
}
#endif /* USE_IPV6 */
return NULL;
}
static bool can_resolve_ip_version(struct Curl_easy *data, int ip_version) static bool can_resolve_ip_version(struct Curl_easy *data, int ip_version)
{ {
#ifdef CURLRES_IPV6 #ifdef CURLRES_IPV6
@ -841,10 +804,10 @@ CURLcode Curl_resolv(struct Curl_easy *data,
struct Curl_dnscache *dnscache = dnscache_get(data); struct Curl_dnscache *dnscache = dnscache_get(data);
struct Curl_dns_entry *dns = NULL; struct Curl_dns_entry *dns = NULL;
struct Curl_addrinfo *addr = NULL; struct Curl_addrinfo *addr = NULL;
int respwait = 0; bool respwait = FALSE;
bool is_ipaddr;
size_t hostname_len; size_t hostname_len;
bool keep_negative = TRUE; /* cache a negative result */ bool keep_negative = TRUE; /* cache a negative result */
CURLcode result = CURLE_COULDNT_RESOLVE_HOST;
*entry = NULL; *entry = NULL;
@ -853,8 +816,11 @@ CURLcode Curl_resolv(struct Curl_easy *data,
#else #else
(void)allowDOH; (void)allowDOH;
#endif #endif
if(!dnscache) DEBUGASSERT(dnscache);
if(!dnscache) {
result = CURLE_BAD_FUNCTION_ARGUMENT;
goto error; goto error;
}
/* We should intentionally error and not resolve .onion TLDs */ /* We should intentionally error and not resolve .onion TLDs */
hostname_len = strlen(hostname); hostname_len = strlen(hostname);
@ -874,6 +840,7 @@ CURLcode Curl_resolv(struct Curl_easy *data,
dnscache_unlock(data, dnscache); dnscache_unlock(data, dnscache);
if(dns) { if(dns) {
infof(data, "Hostname %s was found in DNS cache", hostname); infof(data, "Hostname %s was found in DNS cache", hostname);
result = CURLE_OK;
goto out; goto out;
} }
@ -882,7 +849,8 @@ CURLcode Curl_resolv(struct Curl_easy *data,
void *resolver = NULL; void *resolver = NULL;
int st; int st;
#ifdef CURLRES_ASYNCH #ifdef CURLRES_ASYNCH
if(Curl_async_get_impl(data, &resolver)) result = Curl_async_get_impl(data, &resolver);
if(result)
goto error; goto error;
#endif #endif
Curl_set_in_callback(data, TRUE); Curl_set_in_callback(data, TRUE);
@ -891,57 +859,58 @@ CURLcode Curl_resolv(struct Curl_easy *data,
Curl_set_in_callback(data, FALSE); Curl_set_in_callback(data, FALSE);
if(st) { if(st) {
keep_negative = FALSE; keep_negative = FALSE;
result = CURLE_ABORTED_BY_CALLBACK;
goto error; goto error;
} }
} }
/* shortcut literal IP addresses, if we are not told to resolve them. */ if(Curl_is_ipaddr(hostname)) {
addr = convert_ipaddr_direct(hostname, port, &is_ipaddr);
if(addr)
goto out;
#ifndef USE_RESOLVE_ON_IPS #ifndef USE_RESOLVE_ON_IPS
/* allowed to convert, hostname is IP address, then NULL means error */ /* shortcut literal IP addresses, if we are not told to resolve them. */
if(is_ipaddr) { result = Curl_str2addr(hostname, port, &addr);
keep_negative = FALSE; if(result)
goto error; goto error;
} goto out;
#endif #endif
}
/* Really need a resolver for hostname. */ if(curl_strequal(hostname, "localhost") ||
if(ip_version == CURL_IPRESOLVE_V6 && !Curl_ipv6works(data)) curl_strequal(hostname, "localhost.") ||
goto error; tailmatch(hostname, hostname_len, STRCONST(".localhost")) ||
tailmatch(hostname, hostname_len, STRCONST(".localhost."))) {
if(!is_ipaddr &&
(curl_strequal(hostname, "localhost") ||
curl_strequal(hostname, "localhost.") ||
tailmatch(hostname, hostname_len, STRCONST(".localhost")) ||
tailmatch(hostname, hostname_len, STRCONST(".localhost.")))) {
addr = get_localhost(port, hostname); addr = get_localhost(port, hostname);
result = addr ? CURLE_OK : CURLE_OUT_OF_MEMORY;
} }
#ifndef CURL_DISABLE_DOH #ifndef CURL_DISABLE_DOH
else if(!is_ipaddr && allowDOH && data->set.doh) { else if(!Curl_is_ipaddr(hostname) && allowDOH && data->set.doh) {
addr = Curl_doh(data, hostname, port, ip_version, &respwait); result = Curl_doh(data, hostname, port, ip_version);
respwait = TRUE;
} }
#endif #endif
else { else {
/* Can we provide the requested IP specifics in resolving? */ /* Can we provide the requested IP specifics in resolving? */
if(!can_resolve_ip_version(data, ip_version)) if(!can_resolve_ip_version(data, ip_version)) {
result = CURLE_COULDNT_RESOLVE_HOST;
goto error; goto error;
}
#ifdef CURLRES_ASYNCH #ifdef CURLRES_ASYNCH
addr = Curl_async_getaddrinfo(data, hostname, port, ip_version, &respwait); result = Curl_async_getaddrinfo(data, hostname, port, ip_version);
respwait = TRUE;
#else #else
respwait = 0; /* no async waiting here */ respwait = FALSE; /* no async waiting here */
addr = Curl_sync_getaddrinfo(data, hostname, port, ip_version); addr = Curl_sync_getaddrinfo(data, hostname, port, ip_version);
if(addr)
result = CURLE_OK;
#endif #endif
} }
out: out:
/* We either have found a `dns` or looked up the `addr` /* We either have found a `dns` or looked up the `addr` or `respwait` is set
* or `respwait` is set for an async operation. * for an async operation. Everything else is a failure to resolve. */
* Everything else is a failure to resolve. */ if(result)
if(dns) { ;
else if(dns) {
if(!dns->addr) { if(!dns->addr) {
infof(data, "Negative DNS entry"); infof(data, "Negative DNS entry");
dns->refcount--; dns->refcount--;
@ -955,7 +924,12 @@ out:
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)) { if(!dns || Curl_dnscache_add(data, dns)) {
/* this is OOM or similar, do not store such negative resolves */ /* 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;
keep_negative = FALSE; keep_negative = FALSE;
result = CURLE_OUT_OF_MEMORY;
goto error; goto error;
} }
show_resolve_info(data, dns); show_resolve_info(data, dns);
@ -967,6 +941,7 @@ out:
*entry = dns; *entry = dns;
return dns ? CURLE_OK : CURLE_AGAIN; return dns ? CURLE_OK : CURLE_AGAIN;
} }
result = CURLE_COULDNT_RESOLVE_HOST;
} }
error: error:
if(dns) if(dns)
@ -974,7 +949,8 @@ error:
Curl_async_shutdown(data); Curl_async_shutdown(data);
if(keep_negative) if(keep_negative)
store_negative_resolve(data, hostname, port); store_negative_resolve(data, hostname, port);
return CURLE_COULDNT_RESOLVE_HOST; DEBUGASSERT(result);
return result;
} }
CURLcode Curl_resolv_blocking(struct Curl_easy *data, CURLcode Curl_resolv_blocking(struct Curl_easy *data,
@ -1338,6 +1314,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
while(*host) { while(*host) {
struct Curl_str target; struct Curl_str target;
struct Curl_addrinfo *ai; struct Curl_addrinfo *ai;
CURLcode result;
if(!curlx_str_single(&host, '[')) { if(!curlx_str_single(&host, '[')) {
if(curlx_str_until(&host, &target, MAX_IPADR_LEN, ']') || if(curlx_str_until(&host, &target, MAX_IPADR_LEN, ']') ||
@ -1368,8 +1345,8 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
memcpy(address, curlx_str(&target), curlx_strlen(&target)); memcpy(address, curlx_str(&target), curlx_strlen(&target));
address[curlx_strlen(&target)] = '\0'; address[curlx_strlen(&target)] = '\0';
ai = Curl_str2addr(address, (int)port); result = Curl_str2addr(address, (int)port, &ai);
if(!ai) { if(result) {
infof(data, "Resolve address '%s' found illegal", address); infof(data, "Resolve address '%s' found illegal", address);
goto err; goto err;
} }
@ -1428,11 +1405,12 @@ err:
/* put this new host in the cache */ /* 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); curlx_strlen(&source), (int)port, permanent);
if(dns) { if(dns)
/* release the returned reference; the cache itself will keep the /* release the returned reference; the cache itself will keep the
* entry alive: */ * entry alive: */
dns->refcount--; dns->refcount--;
} else
Curl_freeaddrinfo(head);
dnscache_unlock(data, dnscache); dnscache_unlock(data, dnscache);

View file

@ -82,9 +82,9 @@ static CURLcode test_lib655(const char *URL)
/* this should fail */ /* this should fail */
res = curl_easy_perform(curl); res = curl_easy_perform(curl);
if(res != CURLE_COULDNT_RESOLVE_HOST) { if(res != CURLE_ABORTED_BY_CALLBACK) {
curl_mfprintf(stderr, "curl_easy_perform should have returned " curl_mfprintf(stderr, "curl_easy_perform should have returned "
"CURLE_COULDNT_RESOLVE_HOST but instead returned error %d\n", "CURLE_ABORTED_BY_CALLBACK but instead returned error %d\n",
res); res);
if(res == CURLE_OK) if(res == CURLE_OK)
res = TEST_ERR_FAILURE; res = TEST_ERR_FAILURE;