From f764b3aed25071a380ccce069eb9e3ee8d15bbfd Mon Sep 17 00:00:00 2001 From: Luis Lavena Date: Sat, 30 Jan 2021 23:31:19 -0300 Subject: [PATCH] Fix incorrect lookup in non-root nodes Given the following non-root tree: tree = Tree(Symbol).new tree.add "/prefix/", :prefix tree.add "/prefix/foo", :foo Attempt to lookup for `/foo` was incorrectly identifying `:foo` entry as the correct value. This change ensures that child nodes of the current node are not scanned if key and path being looked up do not match. Fixes #27 --- CHANGELOG.md | 1 + spec/radix/tree_spec.cr | 9 +++++++++ src/radix/tree.cr | 8 ++++++++ 3 files changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5f44d2..6860007 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ so please check *Changed* and *Removed* notes before upgrading. ### Fixed - Correct lookup issue caused by partial shared key with glob [#23](https://github.com/luislavena/radix/issues/23) +- Correct lookup caused by non-root key in suffix [#27](https://github.com/luislavena/radix/issues/27) ### Removed - Remove `Radix::Result#key` since exposes internal details about structure (breaking change) diff --git a/spec/radix/tree_spec.cr b/spec/radix/tree_spec.cr index f848f86..6191118 100644 --- a/spec/radix/tree_spec.cr +++ b/spec/radix/tree_spec.cr @@ -353,6 +353,15 @@ module Radix result.found?.should be_true result.payload.should eq(:tags) end + + it "do not find when lookup for non-root key" do + tree = Tree(Symbol).new + tree.add "/prefix/", :prefix + tree.add "/prefix/foo", :foo + + result = tree.find "/foo" + result.found?.should be_false + end end context "unicode nodes with shared parent" do diff --git a/src/radix/tree.cr b/src/radix/tree.cr index 3d930dd..9cd5194 100644 --- a/src/radix/tree.cr +++ b/src/radix/tree.cr @@ -299,6 +299,14 @@ module Radix end end + # determine if remaining part of key and path are still the same + if (key_reader.has_next? && path_reader.has_next?) && + (key_reader.current_char != path_reader.current_char || + key_reader.peek_next_char != path_reader.peek_next_char) + # path and key differ, skipping + return + end + # still path to walk, check for possible trailing slash or children # nodes if path_reader.has_next?