diff options
author | Robin Burchell <viroteck@viroteck.net> | 2012-03-28 23:56:32 -0700 |
---|---|---|
committer | Robin Burchell <viroteck@viroteck.net> | 2012-03-28 23:56:32 -0700 |
commit | cfac6a9562764dd1530ed39767630e26934c4685 (patch) | |
tree | d4c59f63c9aa884802a3a2b71bd8f1ddfe5ea8ca /src | |
parent | 7fcda51612c27ecbe7c78a535266d306e285afb0 (diff) | |
parent | 58c893e834ff20495d007709220881a3ff13f423 (diff) |
Merge pull request #16 from Adam-/insp20
Fixed out of bounds memory access from malformed DNS queries that have a...
Diffstat (limited to 'src')
-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)) |