From 3679f4cb5f4397130d8acb67982d293a06a2a9b9 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Fri, 7 Jun 2019 12:21:00 +0200 Subject: [PATCH] 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. (cherry picked from commit 99517c1b39226e50e1eb1a5a6509844fb57e9e68) --- pdns/dnsname.hh | 19 ++++++++++++++----- pdns/test-dnsname_cc.cc | 11 +++++++++-- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/pdns/dnsname.hh b/pdns/dnsname.hh index e5f6b11db..ab2e0aad4 100644 --- a/pdns/dnsname.hh +++ b/pdns/dnsname.hh @@ -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 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) diff --git a/pdns/test-dnsname_cc.cc b/pdns/test-dnsname_cc.cc index 833f2fc31..2e8ecf331 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); -- 2.49.0