File glibc-CVE-2015-7547-patch_2of3_res_query.c.diff of Package glibc.4601
diff -rNU 20 ../glibc-2.18-orig/resolv/res_query.c ./resolv/res_query.c
--- ../glibc-2.18-orig/resolv/res_query.c 2013-08-11 00:52:55.000000000 +0200
+++ ./resolv/res_query.c 2016-02-17 19:13:16.000000000 +0100
@@ -374,80 +374,82 @@
* Also, query 'as is', if there is a trailing dot in the name.
*/
saved_herrno = -1;
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)
return (ret);
saved_herrno = h_errno;
tried_as_is++;
if (answerp && *answerp != answer) {
answer = *answerp;
anslen = MAXPACKET;
}
if (answerp2
&& (*answerp2 < answer || *answerp2 >= answer + anslen))
{
free (*answerp2);
*answerp2 = NULL;
+ *nanswerp2 = 0;
}
}
/*
* We do at least one level of search if
* - there is no dot and RES_DEFNAME is set, or
* - there is at least one dot, there is no trailing dot,
* and RES_DNSRCH is set.
*/
if ((!dots && (statp->options & RES_DEFNAMES) != 0) ||
(dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0)) {
int done = 0;
for (domain = (const char * const *)statp->dnsrch;
*domain && !done;
domain++) {
searched = 1;
if (domain[0][0] == '\0' ||
(domain[0][0] == '.' && domain[0][1] == '\0'))
root_on_list++;
ret = __libc_res_nquerydomain(statp, name, *domain,
class, type,
answer, anslen, answerp,
answerp2, nanswerp2,
resplen2);
if (ret > 0)
return (ret);
if (answerp && *answerp != answer) {
answer = *answerp;
anslen = MAXPACKET;
}
if (answerp2
&& (*answerp2 < answer
|| *answerp2 >= answer + anslen))
{
free (*answerp2);
*answerp2 = NULL;
+ *nanswerp2 = 0;
}
/*
* If no server present, give up.
* If name isn't found in this domain,
* keep trying higher domains in the search list
* (if that's enabled).
* On a NO_DATA error, keep trying, otherwise
* a wildcard entry of another type could keep us
* from finding this entry higher in the domain.
* If we get some other error (negative answer or
* server failure), then stop searching up,
* but try the input name below in case it's
* fully-qualified.
*/
if (errno == ECONNREFUSED) {
RES_SET_H_ERRNO(statp, TRY_AGAIN);
return (-1);
}
@@ -485,40 +487,41 @@
if ((dots || !searched || (statp->options & RES_NOTLDQUERY) == 0)
&& !(tried_as_is || root_on_list)) {
ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
answer, anslen, answerp,
answerp2, nanswerp2, resplen2);
if (ret > 0)
return (ret);
}
/* if we got here, we didn't satisfy the search.
* if we did an initial full query, return that query's H_ERRNO
* (note that we wouldn't be here if that query had succeeded).
* else if we ever got a nodata, send that back as the reason.
* else send back meaningless H_ERRNO, that being the one from
* the last DNSRCH we did.
*/
if (answerp2 && (*answerp2 < answer || *answerp2 >= answer + anslen))
{
free (*answerp2);
*answerp2 = NULL;
+ *nanswerp2 = 0;
}
if (saved_herrno != -1)
RES_SET_H_ERRNO(statp, saved_herrno);
else if (got_nodata)
RES_SET_H_ERRNO(statp, NO_DATA);
else if (got_servfail)
RES_SET_H_ERRNO(statp, TRY_AGAIN);
return (-1);
}
libresolv_hidden_def (__libc_res_nsearch)
int
res_nsearch(res_state statp,
const char *name, /* domain name */
int class, int type, /* class and type of query */
u_char *answer, /* buffer to put answer */
int anslen) /* size of answer */
{
return __libc_res_nsearch(statp, name, class, type, answer,
anslen, NULL, NULL, NULL, NULL);