diff options
Diffstat (limited to 'src/libexpr')
-rw-r--r-- | src/libexpr/eval.cc | 24 | ||||
-rw-r--r-- | src/libexpr/eval.hh | 8 |
2 files changed, 23 insertions, 9 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 353097f89713..2473157b3f63 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -307,6 +307,8 @@ EvalState::EvalState(const Strings & _searchPath, ref<Store> store) assert(gcInitialised); + static_assert(sizeof(Env) == 16); + /* Initialise the Nix expression search path. */ if (!settings.pureEval) { Strings paths = parseNixPath(getEnv("NIX_PATH", "")); @@ -352,6 +354,10 @@ Path EvalState::checkSourcePath(const Path & path_) { if (!allowedPaths) return path_; + auto i = resolvedPaths.find(path_); + if (i != resolvedPaths.end()) + return i->second; + bool found = false; for (auto & i : *allowedPaths) { @@ -369,8 +375,10 @@ Path EvalState::checkSourcePath(const Path & path_) Path path = canonPath(path_, true); for (auto & i : *allowedPaths) { - if (isDirOrInDir(path, i)) + if (isDirOrInDir(path, i)) { + resolvedPaths[path_] = path; return path; + } } throw RestrictedPathError("access to path '%1%' is forbidden in restricted mode", path); @@ -562,12 +570,12 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval) if (!var.fromWith) return env->values[var.displ]; while (1) { - if (!env->haveWithAttrs) { + if (env->type == Env::HasWithExpr) { if (noEval) return 0; Value * v = allocValue(); evalAttrs(*env->up, (Expr *) env->values[0], *v); env->values[0] = v; - env->haveWithAttrs = true; + env->type = Env::HasWithAttrs; } Bindings::iterator j = env->values[0]->attrs->find(var.name); if (j != env->values[0]->attrs->end()) { @@ -597,6 +605,7 @@ Env & EvalState::allocEnv(size_t size) nrValuesInEnvs += size; Env * env = (Env *) allocBytes(sizeof(Env) + size * sizeof(Value *)); env->size = (decltype(Env::size)) size; + env->type = Env::Plain; /* We assume that env->values has been cleared by the allocator; maybeThunk() and lookupVar fromWith expect this. */ @@ -1199,7 +1208,7 @@ void ExprWith::eval(EvalState & state, Env & env, Value & v) Env & env2(state.allocEnv(1)); env2.up = &env; env2.prevWith = prevWith; - env2.haveWithAttrs = false; + env2.type = Env::HasWithExpr; env2.values[0] = (Value *) attrs; body->eval(state, env2, v); @@ -1857,9 +1866,10 @@ size_t valueSize(Value & v) size_t sz = sizeof(Env) + sizeof(Value *) * env.size; - for (size_t i = 0; i < env.size; ++i) - if (env.values[i]) - sz += doValue(*env.values[i]); + if (env.type != Env::HasWithExpr) + for (size_t i = 0; i < env.size; ++i) + if (env.values[i]) + sz += doValue(*env.values[i]); if (env.up) sz += doEnv(*env.up); diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 86e93a5ac9ce..3725e45dad9b 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -7,6 +7,7 @@ #include "hash.hh" #include <map> +#include <unordered_map> namespace nix { @@ -34,8 +35,8 @@ struct Env { Env * up; unsigned short size; // used by ‘valueSize’ - unsigned short prevWith:15; // nr of levels up to next `with' environment - unsigned short haveWithAttrs:1; + unsigned short prevWith:14; // nr of levels up to next `with' environment + enum { Plain = 0, HasWithExpr, HasWithAttrs } type:2; Value * values[0]; }; @@ -100,6 +101,9 @@ private: std::map<std::string, std::pair<bool, std::string>> searchPathResolved; + /* Cache used by checkSourcePath(). */ + std::unordered_map<Path, Path> resolvedPaths; + public: EvalState(const Strings & _searchPath, ref<Store> store); |