From: Pieter Lexis Date: Wed, 7 Jan 2026 10:21:41 +0000 (+0100) Subject: fix(dnsparser): bound check inner ALPN length against tota size X-Git-Tag: rec-5.4.0-beta1~7^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4814e2b306af38f2ad17a6544a73eb083fcb6f7e;p=thirdparty%2Fpdns.git fix(dnsparser): bound check inner ALPN length against tota size --- diff --git a/pdns/dnsparser.cc b/pdns/dnsparser.cc index 8f17d81fff..32a09b163a 100644 --- a/pdns/dnsparser.cc +++ b/pdns/dnsparser.cc @@ -646,6 +646,9 @@ void PacketReader::xfrSvcParamKeyVals(set &kvs) { if (alpnLen == 0) { throw std::out_of_range("alpn length of 0"); } + if (d_pos + alpnLen > stop) { + throw std::out_of_range("alpn length is larger than rest of alpn SVC Param"); + } xfrBlob(alpn, alpnLen); alpns.push_back(std::move(alpn)); } diff --git a/pdns/test-dnsparser_cc.cc b/pdns/test-dnsparser_cc.cc index 18467908b8..47113dc110 100644 --- a/pdns/test-dnsparser_cc.cc +++ b/pdns/test-dnsparser_cc.cc @@ -618,6 +618,31 @@ BOOST_AUTO_TEST_CASE(test_clearDNSPacketUnsafeRecordTypes) { } +BOOST_AUTO_TEST_CASE(test_xfrSvcParamKeyVals_alpn_length_wrong) { + vector fakePacket { + 0x00, 0x01, // Key 1 (ALPN) + 0x00, 0x04, // length 3 + 0x01, // ALPN length, too short + // This means '2' is the length for the next ALPN + 'h', '2' + }; + + PacketReader pr(std::string_view(reinterpret_cast(fakePacket.data()), fakePacket.size()), 0); + + std::set svcParams; + + BOOST_CHECK_THROW(pr.xfrSvcParamKeyVals(svcParams), std::out_of_range); + + fakePacket = { + 0x00, 0x01, // Key 1 (ALPN) + 0x00, 0x03, // length 3 + 0x03, // ALPN length 3 (too long, i.e. after end of SVC Params) + 'h', '2' + }; + + BOOST_CHECK_THROW(pr.xfrSvcParamKeyVals(svcParams), std::out_of_range); +} + BOOST_AUTO_TEST_CASE(test_xfrSvcParamKeyVals_multiple) { vector fakePacket { 0x00, 0x01, // Key 1 (ALPN)