diff options
author | Adam <Adam@anope.org> | 2012-03-27 21:39:50 -0400 |
---|---|---|
committer | Adam <Adam@anope.org> | 2012-03-27 21:39:50 -0400 |
commit | 58c893e834ff20495d007709220881a3ff13f423 (patch) | |
tree | d4c59f63c9aa884802a3a2b71bd8f1ddfe5ea8ca | |
parent | ed28c1ba666b39581adb860bf51cdde43c84cc89 (diff) |
Fixed infinite loop cauesd by invalid dns packets
-rw-r--r-- | src/dns.cpp | 11 |
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)) |