@@ -68,7 +68,13 @@ class FSPermission final : public PermissionBase {
6868 return split_child->CreateChild (path_prefix.substr (i));
6969 }
7070 }
71- child->is_leaf = true ;
71+ // Only mark the child as a leaf when it already terminates an
72+ // inserted path. Routing a longer path through this node must not
73+ // turn a pass-through prefix into a granted entry, or an unrelated
74+ // parent directory would be treated as allowed.
75+ if (child->IsEndNode ()) {
76+ child->is_leaf = true ;
77+ }
7278 return child->CreateChild (path_prefix.substr (i));
7379 }
7480
@@ -137,6 +143,31 @@ class FSPermission final : public PermissionBase {
137143 }
138144 return is_leaf;
139145 }
146+
147+ // A directory allowed with a trailing wildcard ("/dir/*") also grants
148+ // access to the directory itself. After a radix split that grant is
149+ // stored as a "/" + "*" descendant of this node rather than on the
150+ // node, so look for it explicitly.
151+ bool HasWildcardGrantForSelf () const {
152+ const char pattern[2 ] = {node::kPathSeparator , ' *' };
153+ size_t matched = 0 ;
154+ const Node* current = this ;
155+ while (matched < 2 ) {
156+ auto it = current->children .find (pattern[matched]);
157+ if (it == current->children .end ()) {
158+ return false ;
159+ }
160+ const Node* child = it->second ;
161+ for (size_t i = 0 ; i < child->prefix .length (); ++i) {
162+ if (matched >= 2 || child->prefix [i] != pattern[matched]) {
163+ return false ;
164+ }
165+ ++matched;
166+ }
167+ current = child;
168+ }
169+ return current->wildcard_child != nullptr ;
170+ }
140171 };
141172
142173 RadixTree ();
0 commit comments