]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsparser: Harden the DNS parser against malformed records
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 16 Mar 2026 14:55:29 +0000 (15:55 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 31 Mar 2026 10:31:42 +0000 (12:31 +0200)
There is no security issue: we are not reading outside of the packet
or bypassing any checks. We might however accept packets that are not
valid and that we could discard earlier in the process.

Reported by nrabrenovic in YWH-PGM6095-137.

Signed-off-by: Remi Gacogne <remi.gacogne@powerdns.com>
pdns/dnsparser.cc
pdns/dnsparser.hh

index 32a09b163a65489821411bd8b1b5aae322acbb21..6b66788380505c734ce972f12e044d9231cec356 100644 (file)
@@ -502,25 +502,33 @@ string PacketReader::getText(bool multi, bool lenField)
 {
   string ret;
   ret.reserve(40);
-  while(d_pos < d_startrecordpos + d_recordlen ) {
-    if(!ret.empty()) {
+  while (d_pos < d_startrecordpos + d_recordlen ) {
+    if (!ret.empty()) {
       ret.append(1,' ');
     }
     uint16_t labellen;
-    if(lenField)
-      labellen=static_cast<uint8_t>(d_content.at(d_pos++));
-    else
-      labellen=d_recordlen - (d_pos - d_startrecordpos);
-
-    ret.append(1,'"');
-    if(labellen) { // no need to do anything for an empty string
-      string val(&d_content.at(d_pos), &d_content.at(d_pos+labellen-1)+1);
+    if (lenField) {
+      labellen = static_cast<uint8_t>(d_content.at(d_pos++));
+    }
+    else {
+      labellen = d_recordlen - (d_pos - d_startrecordpos);
+    }
+
+    const uint16_t remaining = (d_startrecordpos + d_recordlen) - d_pos;
+    if (labellen > remaining) {
+      throw std::out_of_range("label length in text record exceeds record boundary");
+    }
+
+    ret.append(1, '"');
+    if (labellen) { // no need to do anything for an empty string
+      string val(&d_content.at(d_pos), &d_content.at(d_pos + labellen - 1) + 1);
       ret.append(txtEscape(val)); // the end is one beyond the packet
     }
-    ret.append(1,'"');
-    d_pos+=labellen;
-    if(!multi)
+    ret.append(1, '"');
+    d_pos += labellen;
+    if (!multi) {
       break;
+    }
   }
 
   if (ret.empty() && !lenField) {
index 019171d7feb5e78f435f7170995e15c550a182b0..fa79f2534a43d3c06968c293a474a9b3cff9cf48 100644 (file)
@@ -165,7 +165,11 @@ public:
   string getUnquotedText(bool lenField);
 
 
-  bool eof() { return true; };
+  bool eof() const
+  {
+    return d_pos >= (d_startrecordpos + d_recordlen);
+  }
+
   const string getRemaining() const {
     return "";
   };