]> 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)
committerOtto Moerbeek <otto.moerbeek@open-xchange.com>
Wed, 19 Jun 2019 12:21:31 +0000 (14:21 +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.

(cherry picked from commit 99517c1b39226e50e1eb1a5a6509844fb57e9e68)

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

index e5f6b11dbbaa639f51910068aa47ee3dca260c84..ab2e0aad4ec1a829175c31b5ce6194d03f37f7d9 100644 (file)
@@ -328,9 +328,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
@@ -338,7 +343,7 @@ struct SuffixMatchTree
     if(labels.empty()) { // optimization
       if(endNode)
         return &d_value;
-      return 0;
+      return nullptr;
     }
 
     SuffixMatchTree smn(*labels.rbegin());
@@ -346,10 +351,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);