From: Remi Gacogne Date: Fri, 7 Dec 2018 10:13:17 +0000 (+0100) Subject: Ensure a valid range to string::assign() in PacketReader::xfrBlob() X-Git-Tag: rec-4.2.0-alpha1~90^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b4d358e79b23a6eb13680b13348e554da820fd89;p=thirdparty%2Fpdns.git Ensure a valid range to string::assign() in PacketReader::xfrBlob() In some cases we could have called: std::string::assign(InputIterator first, InputIterator last) with last < first, which is UB: if the range specified by [first,last) is not valid, it causes undefined behavior libstdc++ handles that gracefully by throwing an out-of-range exception but libc++ tries to allocate a negative value of bytes, which in turns triggers a request for a very large memory allocation, which fails. --- diff --git a/pdns/dnsparser.cc b/pdns/dnsparser.cc index 61fe23e929..1878fc6b90 100644 --- a/pdns/dnsparser.cc +++ b/pdns/dnsparser.cc @@ -496,10 +496,15 @@ string PacketReader::getUnquotedText(bool lenField) void PacketReader::xfrBlob(string& blob) try { - if(d_recordlen && !(d_pos == (d_startrecordpos + d_recordlen))) + if(d_recordlen && !(d_pos == (d_startrecordpos + d_recordlen))) { + if (d_pos > (d_startrecordpos + d_recordlen)) { + throw std::out_of_range("xfrBlob out of record range"); + } blob.assign(&d_content.at(d_pos), &d_content.at(d_startrecordpos + d_recordlen - 1 ) + 1); - else + } + else { blob.clear(); + } d_pos = d_startrecordpos + d_recordlen; } @@ -515,12 +520,17 @@ void PacketReader::xfrBlobNoSpaces(string& blob, int length) { void PacketReader::xfrBlob(string& blob, int length) { if(length) { + if (length < 0) { + throw std::out_of_range("xfrBlob out of range (negative length)"); + } + blob.assign(&d_content.at(d_pos), &d_content.at(d_pos + length - 1 ) + 1 ); - + d_pos += length; } - else + else { blob.clear(); + } }