summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2012-03-27 21:39:50 -0400
committerAdam <Adam@anope.org>2012-03-27 21:39:50 -0400
commit58c893e834ff20495d007709220881a3ff13f423 (patch)
treed4c59f63c9aa884802a3a2b71bd8f1ddfe5ea8ca
parented28c1ba666b39581adb860bf51cdde43c84cc89 (diff)
Fixed infinite loop cauesd by invalid dns packets
-rw-r--r--src/dns.cpp11
1 files changed, 9 insertions, 2 deletions
diff --git a/src/dns.cpp b/src/dns.cpp
index be74e6aa3..58cbcca76 100644
--- a/src/dns.cpp
+++ b/src/dns.cpp
@@ -800,6 +800,8 @@ DNSInfo DNSRequest::ResultIsReady(DNSHeader &header, unsigned length)
*/
case DNS_QUERY_CNAME:
case DNS_QUERY_PTR:
+ {
+ unsigned short lowest_pos = length;
o = 0;
q = 0;
while (q == 0 && i < length && o + 256 < 1023)
@@ -812,14 +814,18 @@ DNSInfo DNSRequest::ResultIsReady(DNSHeader &header, unsigned length)
i = ntohs(ptr);
/* check that highest two bits are set. if not, we've been had */
- if (!(i & DN_COMP_BITMASK))
+ if ((i & DN_COMP_BITMASK) != DN_COMP_BITMASK)
return std::make_pair((unsigned char *) NULL, "DN label decompression header is bogus");
/* mask away the two highest bits. */
i &= ~DN_COMP_BITMASK;
/* and decrease length by 12 bytes. */
- i =- 12;
+ i -= 12;
+
+ if (i >= lowest_pos)
+ return std::make_pair((unsigned char *) NULL, "Invalid decompression pointer");
+ lowest_pos = i;
}
else
{
@@ -843,6 +849,7 @@ DNSInfo DNSRequest::ResultIsReady(DNSHeader &header, unsigned length)
}
}
res[o] = 0;
+ }
break;
case DNS_QUERY_AAAA:
if (rr.rdlength != sizeof(struct in6_addr))