]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
limit compression pointers to 14 bits
authorPeter van Dijk <peter.van.dijk@powerdns.com>
Fri, 5 Jul 2019 09:46:25 +0000 (11:46 +0200)
committerPeter van Dijk <peter.van.dijk@powerdns.com>
Tue, 9 Jul 2019 09:16:38 +0000 (11:16 +0200)
pdns/Makefile.am
pdns/dnswriter.cc
pdns/test-dnswriter_cc.cc [new file with mode: 0644]

index 4f71e11908463761c38db28e64f309078e3b02bd..287899353f45a550b17778a662add36737b7f6fb 100644 (file)
@@ -1316,6 +1316,7 @@ testrunner_SOURCES = \
        test-dnsparser_cc.cc \
        test-dnsparser_hh.cc \
        test-dnsrecords_cc.cc \
+       test-dnswriter_cc.cc \
        test-ipcrypt_cc.cc \
        test-iputils_hh.cc \
        test-ixfr_cc.cc \
index 745e0387a193047652404b32e00adf60afa4f42b..24dad7c0b6d4f5686425ea79ed9bf2d85e6e9997 100644 (file)
@@ -266,7 +266,9 @@ uint16_t DNSPacketWriter::lookupName(const DNSName& name, uint16_t* matchLen)
         }
         if(!c)
           break;
-        pvect.push_back(iter - d_content.cbegin());
+        auto offset = iter - d_content.cbegin();
+        if (offset >= 16384) break; // compression pointers cannot point here
+        pvect.push_back(offset);
         iter+=*iter+1;
       }
     }
@@ -325,7 +327,7 @@ void DNSPacketWriter::xfrName(const DNSName& name, bool compress, bool)
 
   uint16_t li=0;
   uint16_t matchlen=0;
-  if(compress && (li=lookupName(name, &matchlen))) {
+  if(compress && (li=lookupName(name, &matchlen)) && li < 16384) {
     const auto& dns=name.getStorage(); 
     if(l_verbose)
       cout<<"Found a substring of "<<matchlen<<" bytes from the back, offset: "<<li<<", dnslen: "<<dns.size()<<endl;
diff --git a/pdns/test-dnswriter_cc.cc b/pdns/test-dnswriter_cc.cc
new file mode 100644 (file)
index 0000000..b9baa05
--- /dev/null
@@ -0,0 +1,51 @@
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_NO_MAIN
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <boost/test/unit_test.hpp>
+#include <fstream>
+
+#include "dnswriter.hh"
+#include "dnsparser.hh"
+
+BOOST_AUTO_TEST_SUITE(test_dnswriter_cc)
+
+BOOST_AUTO_TEST_CASE(test_compressionBoundary) {
+  DNSName name("powerdns.com.");
+
+  vector<uint8_t> packet;
+  DNSPacketWriter pwR(packet, name, QType::A, QClass::IN, 0);
+  pwR.getHeader()->qr = 1;
+
+  /* record we want to see altered */
+  pwR.startRecord(name, QType::TXT, 3600, QClass::IN, DNSResourceRecord::ANSWER);
+  auto txt = string("\"")+string(16262, 'A')+string("\"");
+  pwR.xfrText(txt);
+  pwR.commit();
+  BOOST_CHECK_EQUAL(pwR.size(), 16368);
+
+  pwR.startRecord(DNSName("mediumsizedlabel.example.net"), QType::A, 3600, QClass::IN, DNSResourceRecord::ANSWER);
+  pwR.xfrIP('P'<<24 |
+            'Q'<<16 |
+            'R'<<8  |
+            'S');
+  pwR.commit();
+  BOOST_CHECK_EQUAL(pwR.size(), 16412); // 16412 (0x401c) puts '7example3net' at 0x4001
+
+  pwR.startRecord(DNSName("adifferentlabel.example.net"), QType::A, 3600, QClass::IN, DNSResourceRecord::ANSWER);
+  pwR.xfrIP('D'<<24 |
+            'E'<<16 |
+            'F'<<8  |
+            'G');
+  pwR.commit();
+  BOOST_CHECK_EQUAL(pwR.size(), 16455);
+
+  string spacket(packet.begin(), packet.end());
+
+  BOOST_CHECK_NO_THROW(MOADNSParser mdp(false, spacket));
+}
+
+BOOST_AUTO_TEST_SUITE_END()