From: Remi Gacogne Date: Mon, 16 Feb 2026 11:32:43 +0000 (+0100) Subject: dnsdist: Fix invalid `substr()` use in the DNS overlay parser X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cb03001b31579d9cb191552eba5012bbd2c9fd2e;p=thirdparty%2Fpdns.git dnsdist: Fix invalid `substr()` use in the DNS overlay parser `std::basic_string_view::substr`'s second parameter is a length, not an iterator or a position, so the existing code was misusing it and creating a view that potentially expanded outside of the packet. However currently the view is never used to read more than `record.d_contentOffset` (we are passing it immediately to `makeComboAddressFromRaw` with `record.d_contentLength` as the length) and `record.d_contentOffset` has been validated right before to be either `4` or `16`, so there is no out-of-bounds read. This issue has been introduced in b6f9a21db93ee25ec665dc5f65e87eb7adebd102 and is not included in any stable release, so no need to backport the fix. Reported by Nyaz360 in YWH-PGM6095-85, thanks a lot! Signed-off-by: Remi Gacogne --- diff --git a/pdns/dnsdistdist/dnsdist-dnsparser.cc b/pdns/dnsdistdist/dnsdist-dnsparser.cc index cfcd5ce86d..7460d801b6 100644 --- a/pdns/dnsdistdist/dnsdist-dnsparser.cc +++ b/pdns/dnsdistdist/dnsdist-dnsparser.cc @@ -248,7 +248,7 @@ namespace RecordParsers } // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage): length is passed in and used to read data - return makeComboAddressFromRaw(4, packet.substr(record.d_contentOffset, record.d_contentOffset + 4).data(), record.d_contentLength); + return makeComboAddressFromRaw(4, packet.substr(record.d_contentOffset, record.d_contentLength).data(), record.d_contentLength); } std::optional parseAAAARecord(const std::string_view& packet, const DNSPacketOverlay::Record& record) @@ -258,19 +258,19 @@ namespace RecordParsers } // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage): length is passed in and used to read data - return makeComboAddressFromRaw(6, packet.substr(record.d_contentOffset, record.d_contentOffset + 16).data(), record.d_contentLength); + return makeComboAddressFromRaw(6, packet.substr(record.d_contentOffset, record.d_contentLength).data(), record.d_contentLength); } std::optional parseAddressRecord(const std::string_view& packet, const DNSPacketOverlay::Record& record) { if (record.d_type == QType::A && record.d_contentLength == 4) { // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage): length is passed in and used to read data - return makeComboAddressFromRaw(4, packet.substr(record.d_contentOffset, record.d_contentOffset + 4).data(), record.d_contentLength); + return makeComboAddressFromRaw(4, packet.substr(record.d_contentOffset, record.d_contentLength).data(), record.d_contentLength); } if (record.d_type == QType::AAAA && record.d_contentLength == 16) { // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage): length is passed in and used to read data - return makeComboAddressFromRaw(6, packet.substr(record.d_contentOffset, record.d_contentOffset + 16).data(), record.d_contentLength); + return makeComboAddressFromRaw(6, packet.substr(record.d_contentOffset, record.d_contentLength).data(), record.d_contentLength); } return {};