From: Remi Gacogne Date: Fri, 7 Jun 2019 10:21:00 +0000 (+0200) Subject: SuffixMatchTree: Fix partial match of non-leaf nodes X-Git-Tag: dnsdist-1.4.0-rc1~122^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=99517c1b39226e50e1eb1a5a6509844fb57e9e68;p=thirdparty%2Fpdns.git SuffixMatchTree: Fix partial match of non-leaf nodes 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. --- diff --git a/pdns/dnsname.hh b/pdns/dnsname.hh index be58ea3c4e..f9e1d0ba30 100644 --- a/pdns/dnsname.hh +++ b/pdns/dnsname.hh @@ -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 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) diff --git a/pdns/test-dnsname_cc.cc b/pdns/test-dnsname_cc.cc index 833f2fc31e..2e8ecf3313 100644 --- a/pdns/test-dnsname_cc.cc +++ b/pdns/test-dnsname_cc.cc @@ -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);