]> granicus.if.org Git - pdns/commitdiff
Ensure a valid range to string::assign() in PacketReader::xfrBlob()
authorRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 7 Dec 2018 10:13:17 +0000 (11:13 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 10 Dec 2018 17:30:21 +0000 (18:30 +0100)
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.

pdns/dnsparser.cc

index 61fe23e9294445bfc670b67665f96819991d96de..1878fc6b90d152e085b632e3aa315e6ef88140ce 100644 (file)
@@ -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();
+  }
 }