From: Remi Gacogne Date: Mon, 16 Mar 2026 14:55:29 +0000 (+0100) Subject: dnsparser: Harden the DNS parser against malformed records X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3e37e40936a4212af3cedfa7cef69695cf3d52de;p=thirdparty%2Fpdns.git dnsparser: Harden the DNS parser against malformed records 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 --- diff --git a/pdns/dnsparser.cc b/pdns/dnsparser.cc index 32a09b163a..6b66788380 100644 --- a/pdns/dnsparser.cc +++ b/pdns/dnsparser.cc @@ -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(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(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) { diff --git a/pdns/dnsparser.hh b/pdns/dnsparser.hh index 019171d7fe..fa79f2534a 100644 --- a/pdns/dnsparser.hh +++ b/pdns/dnsparser.hh @@ -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 ""; };