init_sockaddr() declares hostinfo without initializing it, then calls freeaddrinfo() on it from every getaddrinfo() failure path. POSIX leaves *res unspecified when getaddrinfo() returns an error, so on failure the function frees whatever the stack happened to hold.
ping.c:984 on develop:
int init_sockaddr(struct sockaddr_in *name, const char *hostname, unsigned short int port) {
struct addrinfo hints, *hostinfo; /* never initialized */
int rv, retry_count;
...
rv = getaddrinfo(hostname, NULL, &hints, &hostinfo);
if (rv == 0) {
break;
} else {
switch (rv) {
case EAI_AGAIN:
...
if (hostinfo != NULL) { /* indeterminate */
freeaddrinfo(hostinfo);
}
Five paths do this: EAI_AGAIN twice (lines 1005 and 1014), EAI_FAIL (1023), EAI_MEMORY (1031), and default (1039).
The EAI_AGAIN retry at 1005 is the most reachable. It frees, then continues around the loop for up to three more attempts, so a device whose name is temporarily unresolvable can hit it repeatedly within one call.
init_sockaddr() is called from the ICMP, UDP and TCP ping paths (ping.c:438, 693, 856), once per device per poll cycle for any device configured by hostname. Reaching the bug needs a resolution failure, which is an ordinary condition when a nameserver is slow or a device name is stale.
Present on develop (line 984) and 1.2.x (line 890).
Fix
Initialize hostinfo to NULL at the declaration, and drop the freeaddrinfo() calls on paths where getaddrinfo() allocated nothing.
init_sockaddr()declareshostinfowithout initializing it, then callsfreeaddrinfo()on it from everygetaddrinfo()failure path. POSIX leaves*resunspecified whengetaddrinfo()returns an error, so on failure the function frees whatever the stack happened to hold.ping.c:984ondevelop:Five paths do this:
EAI_AGAINtwice (lines 1005 and 1014),EAI_FAIL(1023),EAI_MEMORY(1031), anddefault(1039).The
EAI_AGAINretry at 1005 is the most reachable. It frees, thencontinues around the loop for up to three more attempts, so a device whose name is temporarily unresolvable can hit it repeatedly within one call.init_sockaddr()is called from the ICMP, UDP and TCP ping paths (ping.c:438,693,856), once per device per poll cycle for any device configured by hostname. Reaching the bug needs a resolution failure, which is an ordinary condition when a nameserver is slow or a device name is stale.Present on
develop(line 984) and1.2.x(line 890).Fix
Initialize
hostinfotoNULLat the declaration, and drop thefreeaddrinfo()calls on paths wheregetaddrinfo()allocated nothing.