From 7312dd24edebda4a9a54debe7c8ac9064e4bd136 Mon Sep 17 00:00:00 2001 From: John Klug Date: Mon, 24 Jul 2017 17:43:40 -0500 Subject: Fix the gethostbyname memory leak --- recipes-core/eglibc/eglibc_%.bbappend | 4 + .../files/cvs-gethostbyname4-memory-leak.patch | 648 +++++++++++++++++++++ 2 files changed, 652 insertions(+) create mode 100644 recipes-core/eglibc/eglibc_%.bbappend create mode 100644 recipes-core/eglibc/files/cvs-gethostbyname4-memory-leak.patch diff --git a/recipes-core/eglibc/eglibc_%.bbappend b/recipes-core/eglibc/eglibc_%.bbappend new file mode 100644 index 0000000..ece3df9 --- /dev/null +++ b/recipes-core/eglibc/eglibc_%.bbappend @@ -0,0 +1,4 @@ +SRC_URI += " file://cvs-gethostbyname4-memory-leak.patch \ + " + +FILESEXTRAPATHS_prepend := "${THISDIR}/files" diff --git a/recipes-core/eglibc/files/cvs-gethostbyname4-memory-leak.patch b/recipes-core/eglibc/files/cvs-gethostbyname4-memory-leak.patch new file mode 100644 index 0000000..3b66a60 --- /dev/null +++ b/recipes-core/eglibc/files/cvs-gethostbyname4-memory-leak.patch @@ -0,0 +1,648 @@ +diff -Naur '--exclude=.git' '--exclude=*.pyc' '--exclude=*.py' '--exclude=*.*~' libc.orig/include/arpa/nameser_compat.h libc/include/arpa/nameser_compat.h +--- libc.orig/include/arpa/nameser_compat.h 2008-05-12 11:38:35.000000000 -0400 ++++ libc/include/arpa/nameser_compat.h 2017-04-06 16:34:20.413823000 -0400 +@@ -1,8 +1,8 @@ + #ifndef _ARPA_NAMESER_COMPAT_ + #include + +-/* Picksome unused number to represent lookups of IPv4 and IPv6 (i.e., +- T_A and T_AAAA). */ +-#define T_UNSPEC 62321 ++/* The number is outside the 16-bit RR type range and is used ++ internally by the implementation. */ ++#define T_QUERY_A_AND_AAAA 439963904 + + #endif +diff -Naur '--exclude=.git' '--exclude=*.pyc' '--exclude=*.py' '--exclude=*.*~' libc.orig/include/resolv.h libc/include/resolv.h +--- libc.orig/include/resolv.h 2013-09-05 18:41:05.000000000 -0400 ++++ libc/include/resolv.h 2017-04-06 16:33:09.853700600 -0400 +@@ -48,11 +48,11 @@ + libc_hidden_proto (__res_state) + + int __libc_res_nquery (res_state, const char *, int, int, u_char *, int, +- u_char **, u_char **, int *, int *); ++ u_char **, u_char **, int *, int *, int *); + int __libc_res_nsearch (res_state, const char *, int, int, u_char *, int, +- u_char **, u_char **, int *, int *); ++ u_char **, u_char **, int *, int *, int *); + int __libc_res_nsend (res_state, const u_char *, int, const u_char *, int, +- u_char *, int, u_char **, u_char **, int *, int *) ++ u_char *, int, u_char **, u_char **, int *, int *, int *) + attribute_hidden; + + libresolv_hidden_proto (_sethtent) +diff -Naur '--exclude=.git' '--exclude=*.pyc' '--exclude=*.py' '--exclude=*.*~' libc.orig/resolv/gethnamaddr.c libc/resolv/gethnamaddr.c +--- libc.orig/resolv/gethnamaddr.c 2013-06-15 13:37:04.000000000 -0400 ++++ libc/resolv/gethnamaddr.c 2017-04-06 16:13:44.727609300 -0400 +@@ -621,7 +621,7 @@ + buf.buf = origbuf = (querybuf *) alloca (1024); + + if ((n = __libc_res_nsearch(&_res, name, C_IN, type, buf.buf->buf, 1024, +- &buf.ptr, NULL, NULL, NULL)) < 0) { ++ &buf.ptr, NULL, NULL, NULL, NULL)) < 0) { + if (buf.buf != origbuf) + free (buf.buf); + Dprintf("res_nsearch failed (%d)\n", n); +@@ -716,12 +716,12 @@ + buf.buf = orig_buf = (querybuf *) alloca (1024); + + n = __libc_res_nquery(&_res, qbuf, C_IN, T_PTR, buf.buf->buf, 1024, +- &buf.ptr, NULL, NULL, NULL); ++ &buf.ptr, NULL, NULL, NULL, NULL); + if (n < 0 && af == AF_INET6 && (_res.options & RES_NOIP6DOTINT) == 0) { + strcpy(qp, "ip6.int"); + n = __libc_res_nquery(&_res, qbuf, C_IN, T_PTR, buf.buf->buf, + buf.buf != orig_buf ? MAXPACKET : 1024, +- &buf.ptr, NULL, NULL, NULL); ++ &buf.ptr, NULL, NULL, NULL, NULL); + } + if (n < 0) { + if (buf.buf != orig_buf) +diff -Naur '--exclude=.git' '--exclude=*.pyc' '--exclude=*.py' '--exclude=*.*~' libc.orig/resolv/nss_dns/dns-canon.c libc/resolv/nss_dns/dns-canon.c +--- libc.orig/resolv/nss_dns/dns-canon.c 2014-01-03 12:51:28.000000000 -0500 ++++ libc/resolv/nss_dns/dns-canon.c 2017-04-06 16:11:49.654787500 -0400 +@@ -62,7 +62,7 @@ + { + int r = __libc_res_nquery (&_res, name, ns_c_in, qtypes[i], + buf, sizeof (buf), &ansp.ptr, NULL, NULL, +- NULL); ++ NULL, NULL); + if (r > 0) + { + /* We need to decode the response. Just one question record. +diff -Naur '--exclude=.git' '--exclude=*.pyc' '--exclude=*.py' '--exclude=*.*~' libc.orig/resolv/nss_dns/dns-host.c libc/resolv/nss_dns/dns-host.c +--- libc.orig/resolv/nss_dns/dns-host.c 2017-04-06 14:03:55.000000000 -0400 ++++ libc/resolv/nss_dns/dns-host.c 2017-04-06 16:12:50.319551700 -0400 +@@ -190,7 +190,7 @@ + host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024); + + n = __libc_res_nsearch (&_res, name, C_IN, type, host_buffer.buf->buf, +- 1024, &host_buffer.ptr, NULL, NULL, NULL); ++ 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL); + if (n < 0) + { + switch (errno) +@@ -225,7 +225,7 @@ + n = __libc_res_nsearch (&_res, name, C_IN, T_A, host_buffer.buf->buf, + host_buffer.buf != orig_host_buffer + ? MAXPACKET : 1024, &host_buffer.ptr, +- NULL, NULL, NULL); ++ NULL, NULL, NULL, NULL); + + if (n < 0) + { +@@ -308,12 +308,13 @@ + u_char *ans2p = NULL; + int nans2p = 0; + int resplen2 = 0; ++ int ans2p_malloced = 0; + + int olderr = errno; + enum nss_status status; +- int n = __libc_res_nsearch (&_res, name, C_IN, T_UNSPEC, ++ int n = __libc_res_nsearch (&_res, name, C_IN, T_QUERY_A_AND_AAAA, + host_buffer.buf->buf, 2048, &host_buffer.ptr, +- &ans2p, &nans2p, &resplen2); ++ &ans2p, &nans2p, &resplen2, &ans2p_malloced); + if (n < 0) + { + switch (errno) +@@ -352,6 +353,10 @@ + resplen2, name, pat, buffer, buflen, + errnop, herrnop, ttlp); + ++ /* Check whether ans2p was separately allocated. */ ++ if (ans2p_malloced) ++ free (ans2p); ++ + if (host_buffer.buf != orig_host_buffer) + free (host_buffer.buf); + +@@ -460,7 +465,7 @@ + strcpy (qp, "].ip6.arpa"); + n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, + host_buffer.buf->buf, 1024, &host_buffer.ptr, +- NULL, NULL, NULL); ++ NULL, NULL, NULL, NULL); + if (n >= 0) + goto got_it_already; + } +@@ -481,14 +486,14 @@ + } + + n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer.buf->buf, +- 1024, &host_buffer.ptr, NULL, NULL, NULL); ++ 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL); + if (n < 0 && af == AF_INET6 && (_res.options & RES_NOIP6DOTINT) == 0) + { + strcpy (qp, "ip6.int"); + n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer.buf->buf, + host_buffer.buf != orig_host_buffer + ? MAXPACKET : 1024, &host_buffer.ptr, +- NULL, NULL, NULL); ++ NULL, NULL, NULL, NULL); + } + if (n < 0) + { +@@ -613,7 +618,8 @@ + int have_to_map = 0; + uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data); + buffer += pad; +- if (__builtin_expect (buflen < sizeof (struct host_data) + pad, 0)) ++ buflen = buflen > pad ? buflen - pad : 0; ++ if (__glibc_unlikely (buflen < sizeof (struct host_data))) + { + /* The buffer is too small. */ + too_small: +@@ -1267,8 +1273,8 @@ + expected application behaviour. Some of the synthesized responses + aren't very well thought out and sometimes appear to imply that + IPv4 responses are always answer 1, and IPv6 responses are always +- answer 2, but that's not true (see the implementation of send_dg +- and send_vc to see response can arrive in any order, particularly ++ answer 2, but that's not true (see the implemetnation of send_dg ++ and send_vc to see response can arrive in any order, particlarly + for UDP). However, we expect it holds roughly enough of the time + that this code works, but certainly needs to be fixed to make this + a more robust implementation. +@@ -1305,12 +1311,12 @@ + ---------------------------------------------- + + [1] If the first response is a success we return success. +- This ignores the state of the second answer and in fact +- incorrectly sets errno and h_errno to that of the second ++ This ignores the state of the second answer and in fact ++ incorrectly sets errno and h_errno to that of the second + answer. However because the response is a success we ignore + *errnop and *h_errnop (though that means you touched errno on +- success). We are being conservative here and returning the +- likely IPv4 response in the first answer as a success. ++ success). We are being conservative here and returning the ++ likely IPv4 response in the first answer as a success. + + [2] If the first response is a recoverable TRYAGAIN we return + that instead of looking at the second response. The +@@ -1364,7 +1370,7 @@ + if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND) + status = status2; + /* Do not return a truncated second response (unless it was +- unavoidable e.g. unrecoverable TRYAGAIN). */ ++ unavoidable e.g. unrecoverable TRYAGAIN). */ + if (status == NSS_STATUS_SUCCESS + && (status2 == NSS_STATUS_TRYAGAIN + && *errnop == ERANGE && *h_errnop != NO_RECOVERY)) +diff -Naur '--exclude=.git' '--exclude=*.pyc' '--exclude=*.py' '--exclude=*.*~' libc.orig/resolv/nss_dns/dns-network.c libc/resolv/nss_dns/dns-network.c +--- libc.orig/resolv/nss_dns/dns-network.c 2014-01-03 12:51:28.000000000 -0500 ++++ libc/resolv/nss_dns/dns-network.c 2017-04-06 16:13:18.561373600 -0400 +@@ -118,18 +118,15 @@ + } net_buffer; + querybuf *orig_net_buffer; + int anslen; +- char *qbuf; + enum nss_status status; + + if (__res_maybe_init (&_res, 0) == -1) + return NSS_STATUS_UNAVAIL; + +- qbuf = strdupa (name); +- + net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024); + +- anslen = __libc_res_nsearch (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf, +- 1024, &net_buffer.ptr, NULL, NULL, NULL); ++ anslen = __libc_res_nsearch (&_res, name, C_IN, T_PTR, net_buffer.buf->buf, ++ 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL); + if (anslen < 0) + { + /* Nothing found. */ +@@ -205,7 +202,7 @@ + net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024); + + anslen = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf, +- 1024, &net_buffer.ptr, NULL, NULL, NULL); ++ 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL); + if (anslen < 0) + { + /* Nothing found. */ +@@ -398,8 +395,8 @@ + + case BYNAME: + { +- char **ap = result->n_aliases++; +- while (*ap != NULL) ++ char **ap; ++ for (ap = result->n_aliases; *ap != NULL; ++ap) + { + /* Check each alias name for being of the forms: + 4.3.2.1.in-addr.arpa = net 1.2.3.4 +diff -Naur '--exclude=.git' '--exclude=*.pyc' '--exclude=*.py' '--exclude=*.*~' libc.orig/resolv/res_mkquery.c libc/resolv/res_mkquery.c +--- libc.orig/resolv/res_mkquery.c 2013-09-05 18:41:05.000000000 -0400 ++++ libc/resolv/res_mkquery.c 2017-04-06 16:13:56.412597600 -0400 +@@ -110,6 +110,10 @@ + int n; + u_char *dnptrs[20], **dpp, **lastdnptr; + ++ if (class < 0 || class > 65535 ++ || type < 0 || type > 65535) ++ return -1; ++ + #ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_nmkquery(%s, %s, %s, %s)\n", +diff -Naur '--exclude=.git' '--exclude=*.pyc' '--exclude=*.py' '--exclude=*.*~' libc.orig/resolv/res_query.c libc/resolv/res_query.c +--- libc.orig/resolv/res_query.c 2017-04-06 14:03:55.000000000 -0400 ++++ libc/resolv/res_query.c 2017-04-06 16:15:04.137842200 -0400 +@@ -98,7 +98,7 @@ + __libc_res_nquerydomain(res_state statp, const char *name, const char *domain, + int class, int type, u_char *answer, int anslen, + u_char **answerp, u_char **answerp2, int *nanswerp2, +- int *resplen2); ++ int *resplen2, int *answerp2_malloced); + + /* + * Formulate a normal query, send, and await answer. +@@ -119,14 +119,15 @@ + u_char **answerp, /* if buffer needs to be enlarged */ + u_char **answerp2, + int *nanswerp2, +- int *resplen2) ++ int *resplen2, ++ int *answerp2_malloced) + { + HEADER *hp = (HEADER *) answer; + HEADER *hp2; + int n, use_malloc = 0; + u_int oflags = statp->_flags; + +- size_t bufsize = (type == T_UNSPEC ? 2 : 1) * QUERYSIZE; ++ size_t bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * QUERYSIZE; + u_char *buf = alloca (bufsize); + u_char *query1 = buf; + int nquery1 = -1; +@@ -141,7 +142,7 @@ + printf(";; res_query(%s, %d, %d)\n", name, class, type); + #endif + +- if (type == T_UNSPEC) ++ if (type == T_QUERY_A_AND_AAAA) + { + n = res_nmkquery(statp, QUERY, name, class, T_A, NULL, 0, NULL, + query1, bufsize); +@@ -194,7 +195,7 @@ + if (__builtin_expect (n <= 0, 0) && !use_malloc) { + /* Retry just in case res_nmkquery failed because of too + short buffer. Shouldn't happen. */ +- bufsize = (type == T_UNSPEC ? 2 : 1) * MAXPACKET; ++ bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * MAXPACKET; + buf = malloc (bufsize); + if (buf != NULL) { + query1 = buf; +@@ -224,7 +225,8 @@ + } + assert (answerp == NULL || (void *) *answerp == (void *) answer); + n = __libc_res_nsend(statp, query1, nquery1, query2, nquery2, answer, +- anslen, answerp, answerp2, nanswerp2, resplen2); ++ anslen, answerp, answerp2, nanswerp2, resplen2, ++ answerp2_malloced); + if (use_malloc) + free (buf); + if (n < 0) { +@@ -316,7 +318,7 @@ + int anslen) /* size of answer buffer */ + { + return __libc_res_nquery(statp, name, class, type, answer, anslen, +- NULL, NULL, NULL, NULL); ++ NULL, NULL, NULL, NULL, NULL); + } + libresolv_hidden_def (res_nquery) + +@@ -335,7 +337,8 @@ + u_char **answerp, + u_char **answerp2, + int *nanswerp2, +- int *resplen2) ++ int *resplen2, ++ int *answerp2_malloced) + { + const char *cp, * const *domain; + HEADER *hp = (HEADER *) answer; +@@ -360,7 +363,7 @@ + if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL) + return (__libc_res_nquery(statp, cp, class, type, answer, + anslen, answerp, answerp2, +- nanswerp2, resplen2)); ++ nanswerp2, resplen2, answerp2_malloced)); + + #ifdef DEBUG + if (statp->options & RES_DEBUG) +@@ -377,8 +380,9 @@ + if (dots >= statp->ndots || trailing_dot) { + ret = __libc_res_nquerydomain(statp, name, NULL, class, type, + answer, anslen, answerp, +- answerp2, nanswerp2, resplen2); +- if (ret > 0 || trailing_dot) ++ answerp2, nanswerp2, resplen2, ++ answerp2_malloced); ++ if (ret > 0 || (ret == 0 && *resplen2 > 0) || trailing_dot) + return (ret); + saved_herrno = h_errno; + tried_as_is++; +@@ -386,12 +390,12 @@ + answer = *answerp; + anslen = MAXPACKET; + } +- if (answerp2 +- && (*answerp2 < answer || *answerp2 >= answer + anslen)) ++ if (answerp2 && *answerp2_malloced) + { + free (*answerp2); + *answerp2 = NULL; + *nanswerp2 = 0; ++ *answerp2_malloced = 0; + } + } + +@@ -418,21 +422,20 @@ + class, type, + answer, anslen, answerp, + answerp2, nanswerp2, +- resplen2); +- if (ret > 0) ++ resplen2, answerp2_malloced); ++ if ((ret > 0) || (ret == 0 && *resplen2 > 0)) + return (ret); + + if (answerp && *answerp != answer) { + answer = *answerp; + anslen = MAXPACKET; + } +- if (answerp2 +- && (*answerp2 < answer +- || *answerp2 >= answer + anslen)) ++ if (answerp2 && *answerp2_malloced) + { + free (*answerp2); + *answerp2 = NULL; + *nanswerp2 = 0; ++ *answerp2_malloced = 0; + } + + /* +@@ -488,8 +491,9 @@ + && !(tried_as_is || root_on_list)) { + ret = __libc_res_nquerydomain(statp, name, NULL, class, type, + answer, anslen, answerp, +- answerp2, nanswerp2, resplen2); +- if (ret > 0) ++ answerp2, nanswerp2, resplen2, ++ answerp2_malloced); ++ if ((ret > 0) || (ret == 0 && *resplen2 > 0)) + return (ret); + } + +@@ -500,11 +504,12 @@ + * else send back meaningless H_ERRNO, that being the one from + * the last DNSRCH we did. + */ +- if (answerp2 && (*answerp2 < answer || *answerp2 >= answer + anslen)) ++ if (answerp2 && *answerp2_malloced) + { + free (*answerp2); + *answerp2 = NULL; + *nanswerp2 = 0; ++ *answerp2_malloced = 0; + } + if (saved_herrno != -1) + RES_SET_H_ERRNO(statp, saved_herrno); +@@ -524,7 +529,7 @@ + int anslen) /* size of answer */ + { + return __libc_res_nsearch(statp, name, class, type, answer, +- anslen, NULL, NULL, NULL, NULL); ++ anslen, NULL, NULL, NULL, NULL, NULL); + } + libresolv_hidden_def (res_nsearch) + +@@ -542,7 +547,8 @@ + u_char **answerp, + u_char **answerp2, + int *nanswerp2, +- int *resplen2) ++ int *resplen2, ++ int *answerp2_malloced) + { + char nbuf[MAXDNAME]; + const char *longname = nbuf; +@@ -584,7 +590,7 @@ + } + return (__libc_res_nquery(statp, longname, class, type, answer, + anslen, answerp, answerp2, nanswerp2, +- resplen2)); ++ resplen2, answerp2_malloced)); + } + + int +@@ -596,7 +602,8 @@ + int anslen) /* size of answer */ + { + return __libc_res_nquerydomain(statp, name, domain, class, type, +- answer, anslen, NULL, NULL, NULL, NULL); ++ answer, anslen, NULL, NULL, NULL, NULL, ++ NULL); + } + libresolv_hidden_def (res_nquerydomain) + +diff -Naur '--exclude=.git' '--exclude=*.pyc' '--exclude=*.py' '--exclude=*.*~' libc.orig/resolv/res_send.c libc/resolv/res_send.c +--- libc.orig/resolv/res_send.c 2017-04-06 14:03:55.000000000 -0400 ++++ libc/resolv/res_send.c 2017-04-06 16:16:12.448561400 -0400 +@@ -120,13 +120,13 @@ + #define MAXPACKET 65536 + #endif + +- ++#ifdef SOCK_NONBLOCK + #ifndef __ASSUME_SOCK_CLOEXEC + static int __have_o_nonblock; + #else + # define __have_o_nonblock 0 + #endif +- ++#endif + + /* From ev_streams.c. */ + +@@ -203,12 +203,12 @@ + static int send_vc(res_state, const u_char *, int, + const u_char *, int, + u_char **, int *, int *, int, u_char **, +- u_char **, int *, int *); ++ u_char **, int *, int *, int *); + static int send_dg(res_state, const u_char *, int, + const u_char *, int, + u_char **, int *, int *, int, + int *, int *, u_char **, +- u_char **, int *, int *); ++ u_char **, int *, int *, int *); + #ifdef DEBUG + static void Aerror(const res_state, FILE *, const char *, int, + const struct sockaddr *); +@@ -360,7 +360,7 @@ + __libc_res_nsend(res_state statp, const u_char *buf, int buflen, + const u_char *buf2, int buflen2, + u_char *ans, int anssiz, u_char **ansp, u_char **ansp2, +- int *nansp2, int *resplen2) ++ int *nansp2, int *resplen2, int *ansp2_malloced) + { + int gotsomewhere, terrno, try, v_circuit, resplen, ns, n; + +@@ -565,7 +565,8 @@ + try = statp->retry; + n = send_vc(statp, buf, buflen, buf2, buflen2, + &ans, &anssiz, &terrno, +- ns, ansp, ansp2, nansp2, resplen2); ++ ns, ansp, ansp2, nansp2, resplen2, ++ ansp2_malloced); + if (n < 0) + return (-1); + if (n == 0 && (buf2 == NULL || *resplen2 == 0)) +@@ -575,7 +576,7 @@ + n = send_dg(statp, buf, buflen, buf2, buflen2, + &ans, &anssiz, &terrno, + ns, &v_circuit, &gotsomewhere, ansp, +- ansp2, nansp2, resplen2); ++ ansp2, nansp2, resplen2, ansp2_malloced); + if (n < 0) + return (-1); + if (n == 0 && (buf2 == NULL || *resplen2 == 0)) +@@ -665,7 +666,7 @@ + const u_char *buf, int buflen, u_char *ans, int anssiz) + { + return __libc_res_nsend(statp, buf, buflen, NULL, 0, ans, anssiz, +- NULL, NULL, NULL, NULL); ++ NULL, NULL, NULL, NULL, NULL); + } + libresolv_hidden_def (res_nsend) + +@@ -709,7 +710,7 @@ + are needed but ANSCP is NULL, then as much of the response as + possible is read into the buffer, but the results will be truncated. + When truncation happens because of a small answer buffer the DNS +- packets header field TC will bet set to 1, indicating a truncated ++ packets header feild TC will bet set to 1, indicating a truncated + message and the rest of the socket data will be read and discarded. + + Answers to the query are stored secondly in *ANSP2 up to a max of +@@ -747,7 +748,7 @@ + const u_char *buf, int buflen, const u_char *buf2, int buflen2, + u_char **ansp, int *anssizp, + int *terrno, int ns, u_char **anscp, u_char **ansp2, int *anssizp2, +- int *resplen2) ++ int *resplen2, int *ansp2_malloced) + { + const HEADER *hp = (HEADER *) buf; + const HEADER *hp2 = (HEADER *) buf2; +@@ -828,7 +829,7 @@ + */ + int recvresp1 = 0; + /* Skip the second response if there is no second query. +- To do that we mark the second response as received. */ ++ To do that we mark the second response as received. */ + int recvresp2 = buf2 == NULL; + uint16_t rlen16; + read_len: +@@ -896,6 +897,8 @@ + } + *thisanssizp = MAXPACKET; + *thisansp = newp; ++ if (thisansp == ansp2) ++ *ansp2_malloced = 1; + anhp = (HEADER *) newp; + /* A uint16_t can't be larger than MAXPACKET + thus it's safe to allocate MAXPACKET but +@@ -993,6 +996,7 @@ + + /* only try IPv6 if IPv6 NS and if not failed before */ + if (nsap->sa_family == AF_INET6 && !statp->ipv6_unavail) { ++#ifdef SOCK_NONBLOCK + if (__builtin_expect (__have_o_nonblock >= 0, 1)) { + EXT(statp).nssocks[ns] = + socket(PF_INET6, SOCK_DGRAM|SOCK_NONBLOCK, +@@ -1005,12 +1009,14 @@ + #endif + } + if (__builtin_expect (__have_o_nonblock < 0, 0)) ++#endif + EXT(statp).nssocks[ns] = + socket(PF_INET6, SOCK_DGRAM, 0); + if (EXT(statp).nssocks[ns] < 0) + statp->ipv6_unavail = errno == EAFNOSUPPORT; + slen = sizeof (struct sockaddr_in6); + } else if (nsap->sa_family == AF_INET) { ++#ifdef SOCK_NONBLOCK + if (__builtin_expect (__have_o_nonblock >= 0, 1)) { + EXT(statp).nssocks[ns] + = socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK, +@@ -1023,6 +1029,7 @@ + #endif + } + if (__builtin_expect (__have_o_nonblock < 0, 0)) ++#endif + EXT(statp).nssocks[ns] + = socket(PF_INET, SOCK_DGRAM, 0); + slen = sizeof (struct sockaddr_in); +@@ -1049,7 +1056,11 @@ + __res_iclose(statp, false); + return (0); + } ++#ifdef SOCK_NONBLOCK + if (__builtin_expect (__have_o_nonblock < 0, 0)) { ++#else ++ { ++#endif + /* Make socket non-blocking. */ + int fl = __fcntl (EXT(statp).nssocks[ns], F_GETFL); + if (fl != -1) +@@ -1083,7 +1094,7 @@ + are needed but ANSCP is NULL, then as much of the response as + possible is read into the buffer, but the results will be truncated. + When truncation happens because of a small answer buffer the DNS +- packets header field TC will bet set to 1, indicating a truncated ++ packets header feild TC will bet set to 1, indicating a truncated + message, while the rest of the UDP packet is discarded. + + Answers to the query are stored secondly in *ANSP2 up to a max of +@@ -1128,7 +1139,7 @@ + const u_char *buf, int buflen, const u_char *buf2, int buflen2, + u_char **ansp, int *anssizp, + int *terrno, int ns, int *v_circuit, int *gotsomewhere, u_char **anscp, +- u_char **ansp2, int *anssizp2, int *resplen2) ++ u_char **ansp2, int *anssizp2, int *resplen2, int *ansp2_malloced) + { + const HEADER *hp = (HEADER *) buf; + const HEADER *hp2 = (HEADER *) buf2; +@@ -1165,7 +1176,7 @@ + int nwritten = 0; + int recvresp1 = 0; + /* Skip the second response if there is no second query. +- To do that we mark the second response as received. */ ++ To do that we mark the second response as received. */ + int recvresp2 = buf2 == NULL; + pfd[0].fd = EXT(statp).nssocks[ns]; + pfd[0].events = POLLOUT; +@@ -1359,6 +1370,8 @@ + if (newp != NULL) { + *thisanssizp = MAXPACKET; + *thisansp = newp; ++ if (thisansp == ansp2) ++ *ansp2_malloced = 1; + } + } + /* We could end up with truncation if anscp was NULL +@@ -1542,6 +1555,7 @@ + retval = reopen (statp, terrno, ns); + if (retval <= 0) + return retval; ++ pfd[0].fd = EXT(statp).nssocks[ns]; + } + } + goto wait; -- cgit v1.2.3