diff options
author | Benno Fünfstück <benno.fuenfstueck@gmail.com> | 2017-05-15 19:32:51 +0200 |
---|---|---|
committer | Benno Fünfstück <benno.fuenfstueck@gmail.com> | 2017-05-15 19:34:18 +0200 |
commit | 5ee06e612a93a30bfa3b2129a3951e0c36f95602 (patch) | |
tree | cc61588bc6098d17168685c1c8b8e1baa9cc9486 /src/libstore/nar-accessor.cc | |
parent | 4412f7c08367b17b3be723ee42df159100d93922 (diff) |
nar-accessor: non-recursive NarMember::find
This avoids a possible stack overflow if directories are very deeply nested.
Diffstat (limited to 'src/libstore/nar-accessor.cc')
-rw-r--r-- | src/libstore/nar-accessor.cc | 42 |
1 files changed, 21 insertions, 21 deletions
diff --git a/src/libstore/nar-accessor.cc b/src/libstore/nar-accessor.cc index ee1cf385c..c84bb1dea 100644 --- a/src/libstore/nar-accessor.cc +++ b/src/libstore/nar-accessor.cc @@ -21,25 +21,6 @@ struct NarMember /* If this is a directory, all the children of the directory. */ std::map<std::string, NarMember> children; - - NarMember* find(const Path & path) - { - if(path == "") return this; - - if(type != FSAccessor::Type::tDirectory) { - return nullptr; - } - - auto split = std::find(path.begin() + 1, path.end(), '/'); - std::string child_name(path.begin() + 1, split); - std::string remaining(split, path.end()); - - auto child = children.find(child_name); - if(child == children.end()) return nullptr; - - return child->second.find(remaining); - } - }; struct NarIndexer : ParseSink, StringSource @@ -114,8 +95,27 @@ struct NarIndexer : ParseSink, StringSource NarMember* find(const Path & path) { Path canon = path == "" ? "" : canonPath(path); - NarMember* result = root.find(canon); - return result; + NarMember* current = &root; + auto end = path.end(); + for(auto it = path.begin(); it != end; ) { + // because it != end, the remaining component is non-empty so we need + // a directory + if(current->type != FSAccessor::Type::tDirectory) return nullptr; + + // skip slash (canonPath above ensures that this is always a slash) + assert(*it == '/'); + it += 1; + + // lookup current component + auto next = std::find(it, end, '/'); + auto child = current->children.find(std::string(it, next)); + if(child == current->children.end()) return nullptr; + current = &child->second; + + it = next; + } + + return current; } NarMember& at(const Path & path) { |