]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
SuffixMatchTree: Fix partial match of non-leaf nodes
authorRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 7 Jun 2019 10:21:00 +0000 (12:21 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 7 Jun 2019 10:24:12 +0000 (12:24 +0200)
If we insert fr and www.domain.fr, domain.fr should not match
www.domain.fr, the leaf node, and it should not match the
intermediary domain.fr node, but it should match the fr
end-node.

pdns/dnsname.hh
pdns/test-dnsname_cc.cc

index be58ea3c4e904c28f8daab0e999b6538ffc2e69b..f9e1d0ba30b1c7ea4773014dbbc1284aa77c2654 100644 (file)
@@ -333,9 +333,14 @@ struct SuffixMatchTree
     if(children.empty()) { // speed up empty set
       if(endNode)
         return &d_value;
-      return 0;
+      return nullptr;
     }
-    return lookup(name.getRawLabels());
+
+    auto result = lookup(name.getRawLabels());
+    if (result) {
+      return result;
+    }
+    return endNode ? &d_value : nullptr;
   }
 
   T* lookup(std::vector<std::string> labels) const
@@ -343,7 +348,7 @@ struct SuffixMatchTree
     if(labels.empty()) { // optimization
       if(endNode)
         return &d_value;
-      return 0;
+      return nullptr;
     }
 
     SuffixMatchTree smn(*labels.rbegin());
@@ -351,10 +356,14 @@ struct SuffixMatchTree
     if(child == children.end()) {
       if(endNode)
         return &d_value;
-      return 0;
+      return nullptr;
     }
     labels.pop_back();
-    return child->lookup(labels);
+    auto result = child->lookup(labels);
+    if (result) {
+      return result;
+    }
+    return endNode ? &d_value : nullptr;
   }
 
   // Returns all end-nodes, fully qualified (not as separate labels)
index 833f2fc31e434015d6072e894969275d5220b663..2e8ecf3313e94855d3de49cf85046b5e2b6067a8 100644 (file)
@@ -508,10 +508,16 @@ BOOST_AUTO_TEST_CASE(test_suffixmatch) {
   BOOST_CHECK(smn.check(examplenet));
   BOOST_CHECK(smn.check(net));
 
-  // Remove .net and check that example.net still exists
+  // Remove .net and the root, and check that example.net still exists
+  smn.remove(g_rootdnsname);
   smn.remove(net);
   BOOST_CHECK_EQUAL(smn.check(net), false);
   BOOST_CHECK(smn.check(examplenet));
+
+  smn.add(DNSName("fr."));
+  smn.add(DNSName("www.sub.domain.fr."));
+  // should not match www.sub.domain.fr. but should still match fr.
+  BOOST_CHECK(smn.check(DNSName("sub.domain.fr.")));
 }
 
 BOOST_AUTO_TEST_CASE(test_suffixmatch_tree) {
@@ -564,7 +570,8 @@ BOOST_AUTO_TEST_CASE(test_suffixmatch_tree) {
   BOOST_REQUIRE(smt.lookup(net));
   BOOST_CHECK_EQUAL(*smt.lookup(net), net);
 
-  // Remove .net, and check that example.net remains
+  // Remove .net and the root, and check that example.net remains
+  smt.remove(g_rootdnsname);
   smt.remove(net);
   BOOST_CHECK(smt.lookup(net) == nullptr);
   BOOST_CHECK_EQUAL(*smt.lookup(examplenet), examplenet);