]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - resolv/res_query.c
Properly fix memory leak in _nss_dns_gethostbyname4_r with big DNS answer
[thirdparty/glibc.git] / resolv / res_query.c
index 88230f43eb7a3979ed4c596074c3ecf420c2bb1e..88c82555004f5bed4791f7a5b3cac8a54be6dd5f 100644 (file)
@@ -98,7 +98,7 @@ static int
 __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,7 +119,8 @@ __libc_res_nquery(res_state statp,
                  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;
@@ -224,7 +225,8 @@ __libc_res_nquery(res_state statp,
        }
        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 @@ res_nquery(res_state statp,
           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 @@ __libc_res_nsearch(res_state statp,
                   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 @@ __libc_res_nsearch(res_state statp,
        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,7 +380,8 @@ __libc_res_nsearch(res_state statp,
        if (dots >= statp->ndots || trailing_dot) {
                ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
                                              answer, anslen, answerp,
-                                             answerp2, nanswerp2, resplen2);
+                                             answerp2, nanswerp2, resplen2,
+                                             answerp2_malloced);
                if (ret > 0 || trailing_dot)
                        return (ret);
                saved_herrno = h_errno;
@@ -386,11 +390,11 @@ __libc_res_nsearch(res_state statp,
                        answer = *answerp;
                        anslen = MAXPACKET;
                }
-               if (answerp2
-                   && (*answerp2 < answer || *answerp2 >= answer + anslen))
+               if (answerp2 && *answerp2_malloced)
                  {
                    free (*answerp2);
                    *answerp2 = NULL;
+                   *answerp2_malloced = 0;
                  }
        }
 
@@ -417,7 +421,7 @@ __libc_res_nsearch(res_state statp,
                                                      class, type,
                                                      answer, anslen, answerp,
                                                      answerp2, nanswerp2,
-                                                     resplen2);
+                                                     resplen2, answerp2_malloced);
                        if (ret > 0)
                                return (ret);
 
@@ -425,12 +429,11 @@ __libc_res_nsearch(res_state statp,
                                answer = *answerp;
                                anslen = MAXPACKET;
                        }
-                       if (answerp2
-                           && (*answerp2 < answer
-                               || *answerp2 >= answer + anslen))
+                       if (answerp2 && *answerp2_malloced)
                          {
                            free (*answerp2);
                            *answerp2 = NULL;
+                           *answerp2_malloced = 0;
                          }
 
                        /*
@@ -486,7 +489,8 @@ __libc_res_nsearch(res_state statp,
            && !(tried_as_is || root_on_list)) {
                ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
                                              answer, anslen, answerp,
-                                             answerp2, nanswerp2, resplen2);
+                                             answerp2, nanswerp2, resplen2,
+                                             answerp2_malloced);
                if (ret > 0)
                        return (ret);
        }
@@ -498,10 +502,11 @@ __libc_res_nsearch(res_state statp,
         * 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;
+           *answerp2_malloced = 0;
          }
        if (saved_herrno != -1)
                RES_SET_H_ERRNO(statp, saved_herrno);
@@ -521,7 +526,7 @@ res_nsearch(res_state statp,
            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)
 
@@ -539,7 +544,8 @@ __libc_res_nquerydomain(res_state statp,
                        u_char **answerp,
                        u_char **answerp2,
                        int *nanswerp2,
-                       int *resplen2)
+                       int *resplen2,
+                       int *answerp2_malloced)
 {
        char nbuf[MAXDNAME];
        const char *longname = nbuf;
@@ -581,7 +587,7 @@ __libc_res_nquerydomain(res_state statp,
        }
        return (__libc_res_nquery(statp, longname, class, type, answer,
                                  anslen, answerp, answerp2, nanswerp2,
-                                 resplen2));
+                                 resplen2, answerp2_malloced));
 }
 
 int
@@ -593,7 +599,8 @@ res_nquerydomain(res_state statp,
            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)