]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
fix(dnsparser): bound check inner ALPN length against tota size
authorPieter Lexis <pieter.lexis@powerdns.com>
Wed, 7 Jan 2026 10:21:41 +0000 (11:21 +0100)
committerPieter Lexis <pieter.lexis@powerdns.com>
Thu, 8 Jan 2026 10:04:34 +0000 (11:04 +0100)
pdns/dnsparser.cc
pdns/test-dnsparser_cc.cc

index 8f17d81fff2444f54f10722e6db55b4b0ed6a2be..32a09b163a65489821411bd8b1b5aae322acbb21 100644 (file)
@@ -646,6 +646,9 @@ void PacketReader::xfrSvcParamKeyVals(set<SvcParam> &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));
       }
index 18467908b8c531d4fb2afa7cfd498b8b3cee723e..47113dc110f3eaa82b002a3550b9f25becf947a8 100644 (file)
@@ -618,6 +618,31 @@ BOOST_AUTO_TEST_CASE(test_clearDNSPacketUnsafeRecordTypes) {
 
 }
 
+BOOST_AUTO_TEST_CASE(test_xfrSvcParamKeyVals_alpn_length_wrong) {
+  vector<uint8_t> 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<const char*>(fakePacket.data()), fakePacket.size()), 0);
+
+  std::set<SvcParam> 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<uint8_t> fakePacket {
     0x00, 0x01, // Key 1 (ALPN)