Check for bad packets in getaddrinfo.c's getanswer.

The near duplicate in gethnamaddr.c was already doing so (this fix
is basically copy and pasted from there, but with both copies modified
to avoid skirting undefined behavior).

Bug: http://b/32322088
Test: browser still works

FPIIM-189: Denial of service vulnerability in Bionic DNS CVE-2017-0422 A-32322088

Change-Id: Ied6662be567fb1bddc7ceb138cae1da77fb57976
(cherry picked from commit 27a4459d945e34fabd7166791a5b862ccea83f23)
(cherry picked from commit 87c0dba7b1b1754d69cc92f2b400a311d6393eed)
(cherry picked from commit 2449e7ce14f73acd75986f39b3140652a0d08538)
diff --git a/libc/dns/net/getaddrinfo.c b/libc/dns/net/getaddrinfo.c
index 829b679..fd6c004 100644
--- a/libc/dns/net/getaddrinfo.c
+++ b/libc/dns/net/getaddrinfo.c
@@ -1290,6 +1290,17 @@
 static const char AskedForGot[] =
 	"gethostby*.getanswer: asked for \"%s\", got \"%s\"";
 
+#define BOUNDED_INCR(x) \
+	do { \
+		BOUNDS_CHECK(cp, x); \
+		cp += (x); \
+	} while (/*CONSTCOND*/0)
+
+#define BOUNDS_CHECK(ptr, count) \
+	do { \
+		if (eom - (ptr) < (count)) { h_errno = NO_RECOVERY; return NULL; } \
+	} while (/*CONSTCOND*/0)
+
 static struct addrinfo *
 getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
     const struct addrinfo *pai)
@@ -1335,7 +1346,8 @@
 	qdcount = ntohs(hp->qdcount);
 	bp = hostbuf;
 	ep = hostbuf + sizeof hostbuf;
-	cp = answer->buf + HFIXEDSZ;
+	cp = answer->buf;
+	BOUNDED_INCR(HFIXEDSZ);
 	if (qdcount != 1) {
 		h_errno = NO_RECOVERY;
 		return (NULL);
@@ -1345,7 +1357,7 @@
 		h_errno = NO_RECOVERY;
 		return (NULL);
 	}
-	cp += n + QFIXEDSZ;
+	BOUNDED_INCR(n + QFIXEDSZ);
 	if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
 		/* res_send() has already verified that the query name is the
 		 * same as the one we sent; this just gets the expanded name
@@ -1370,12 +1382,14 @@
 			continue;
 		}
 		cp += n;			/* name */
+		BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
 		type = _getshort(cp);
  		cp += INT16SZ;			/* type */
 		class = _getshort(cp);
  		cp += INT16SZ + INT32SZ;	/* class, TTL */
 		n = _getshort(cp);
 		cp += INT16SZ;			/* len */
+		BOUNDS_CHECK(cp, n);
 		if (class != C_IN) {
 			/* XXX - debug? syslog? */
 			cp += n;
diff --git a/libc/dns/net/gethnamaddr.c b/libc/dns/net/gethnamaddr.c
index 42f0d0a..75cb2b3 100644
--- a/libc/dns/net/gethnamaddr.c
+++ b/libc/dns/net/gethnamaddr.c
@@ -186,14 +186,13 @@
 
 #define BOUNDED_INCR(x) \
 	do { \
+		BOUNDS_CHECK(cp, x); \
 		cp += (x); \
-		if (cp > eom) \
-			goto no_recovery; \
 	} while (/*CONSTCOND*/0)
 
 #define BOUNDS_CHECK(ptr, count) \
 	do { \
-		if ((ptr) + (count) > eom) \
+		if (eom - (ptr) < (count)) \
 			goto no_recovery; \
 	} while (/*CONSTCOND*/0)