diff options
-rw-r--r-- | src/dns.cpp | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/src/dns.cpp b/src/dns.cpp index 2e1c751c4..58cbcca76 100644 --- a/src/dns.cpp +++ b/src/dns.cpp @@ -760,7 +760,7 @@ DNSInfo DNSRequest::ResultIsReady(DNSHeader &header, unsigned length) else i += header.payload[i] + 1; /* skip length and label */ } } - if (length - i < 10) + if (static_cast<int>(length - i) < 10) return std::make_pair((unsigned char*)NULL,"Incorrectly sized DNS reply"); /* XXX: We actually initialise 'rr' here including its ttl field */ @@ -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)) |