summaryrefslogtreecommitdiffstats
path: root/src/libstore/nar-accessor.cc
diff options
context:
space:
mode:
authorBenno Fünfstück <benno.fuenfstueck@gmail.com>2017-05-15 19:32:51 +0200
committerBenno Fünfstück <benno.fuenfstueck@gmail.com>2017-05-15 19:34:18 +0200
commit5ee06e612a93a30bfa3b2129a3951e0c36f95602 (patch)
treecc61588bc6098d17168685c1c8b8e1baa9cc9486 /src/libstore/nar-accessor.cc
parent4412f7c08367b17b3be723ee42df159100d93922 (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.cc42
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) {