about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2002-11-18 04:10:15 +0000
committerRoland McGrath <roland@gnu.org>2002-11-18 04:10:15 +0000
commit9b57c1c1e4c6889f47b200bcefe77f16becd2095 (patch)
treef39b189035c84a36febcf825e13d76339d9afd19
parent502328b25830408ad6d8c5d6adf86fe88f3f10d6 (diff)
downloadglibc-9b57c1c1e4c6889f47b200bcefe77f16becd2095.tar.gz
glibc-9b57c1c1e4c6889f47b200bcefe77f16becd2095.tar.xz
glibc-9b57c1c1e4c6889f47b200bcefe77f16becd2095.zip
2002-11-14 Paul Eggert <eggert@twionsun.com>
        * resolv/nss_dns/dns-network.c (getanswer_r): Check for buffer
        overflow when skipping the question part and when unpacking
        aliases.
-rw-r--r--ChangeLog6
-rw-r--r--resolv/nss_dns/dns-network.c25
2 files changed, 24 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index 07eac3bd5f..0bfa1970a8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2002-11-14  Paul Eggert  <eggert@twionsun.com>
+
+        * resolv/nss_dns/dns-network.c (getanswer_r): Check for buffer
+        overflow when skipping the question part and when unpacking
+        aliases.
+
 2002-11-15  Roland McGrath  <roland@redhat.com>
 
 	* math/Makefile (libm-calls): Remove s_copysign, s_isinf, s_isnan,
diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c
index 5956c84382..fdab996837 100644
--- a/resolv/nss_dns/dns-network.c
+++ b/resolv/nss_dns/dns-network.c
@@ -283,7 +283,15 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
 
   /* Skip the question part.  */
   while (question_count-- > 0)
-    cp += __dn_skipname (cp, end_of_message) + QFIXEDSZ;
+    {
+      int n = __dn_skipname (cp, end_of_message);
+      if (n < 0 || end_of_message - (cp + n) < QFIXEDSZ)
+       {
+         __set_h_errno (NO_RECOVERY);
+         return NSS_STATUS_UNAVAIL;
+       }
+      cp += n + QFIXEDSZ;
+    }
 
   alias_pointer = result->n_aliases = &net_data->aliases[0];
   *alias_pointer = NULL;
@@ -344,12 +352,15 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
 	      return NSS_STATUS_UNAVAIL;
 	    }
 	  cp += n;
-	  *alias_pointer++ = bp;
-	  n = strlen (bp) + 1;
-	  bp += n;
-	  linebuflen -= n;
-	  result->n_addrtype = class == C_IN ? AF_INET : AF_UNSPEC;
-	  ++have_answer;
+         if (alias_pointer + 2 < &net_data->aliases[MAX_NR_ALIASES])
+           {
+             *alias_pointer++ = bp;
+             n = strlen (bp) + 1;
+             bp += n;
+             linebuflen -= n;
+             result->n_addrtype = class == C_IN ? AF_INET : AF_UNSPEC;
+             ++have_answer;
+           }
 	}
     }