From e7ed9ae0c711c4efd83756b16379549ecff52355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Na=C3=AFm=20Favier?= Date: Fri, 4 Nov 2022 14:19:31 +0100 Subject: Restrict `readFile` context to references that appear in the string When calling `builtins.readFile` on a store path, the references of that path are currently added to the resulting string's context. This change makes those references the *possible* context of the string, but filters them to keep only the references whose hash actually appears in the string, similarly to what is done for determining the runtime references of a path. --- src/libexpr/primops.cc | 5 +++++ src/libstore/references.cc | 53 ++++++++++++++++++++++++++++++---------------- src/libstore/references.hh | 13 ++++++++++++ 3 files changed, 53 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 28b998474..ff620ca63 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -5,6 +5,7 @@ #include "globals.hh" #include "json-to-value.hh" #include "names.hh" +#include "references.hh" #include "store-api.hh" #include "util.hh" #include "json.hh" @@ -1542,6 +1543,10 @@ static void prim_readFile(EvalState & state, const PosIdx pos, Value * * args, V refs = state.store->queryPathInfo(state.store->toStorePath(path).first)->references; } catch (Error &) { // FIXME: should be InvalidPathError } + // Re-scan references to filter down to just the ones that actually occur in the file. + auto refsSink = PathRefScanSink::fromPaths(refs); + refsSink << s; + refs = refsSink.getResultPaths(); } auto context = state.store->printStorePathSet(refs); v.mkString(s, context); diff --git a/src/libstore/references.cc b/src/libstore/references.cc index 34dce092c..3bb297fc8 100644 --- a/src/libstore/references.cc +++ b/src/libstore/references.cc @@ -67,20 +67,12 @@ void RefScanSink::operator () (std::string_view data) } -std::pair scanForReferences( - const std::string & path, - const StorePathSet & refs) -{ - HashSink hashSink { htSHA256 }; - auto found = scanForReferences(hashSink, path, refs); - auto hash = hashSink.finish(); - return std::pair(found, hash); -} +PathRefScanSink::PathRefScanSink(StringSet && hashes, std::map && backMap) + : RefScanSink(std::move(hashes)) + , backMap(std::move(backMap)) +{ } -StorePathSet scanForReferences( - Sink & toTee, - const Path & path, - const StorePathSet & refs) +PathRefScanSink PathRefScanSink::fromPaths(const StorePathSet & refs) { StringSet hashes; std::map backMap; @@ -92,14 +84,14 @@ StorePathSet scanForReferences( hashes.insert(hashPart); } - /* Look for the hashes in the NAR dump of the path. */ - RefScanSink refsSink(std::move(hashes)); - TeeSink sink { refsSink, toTee }; - dumpPath(path, sink); + return PathRefScanSink(std::move(hashes), std::move(backMap)); +} +StorePathSet PathRefScanSink::getResultPaths() +{ /* Map the hashes found back to their store paths. */ StorePathSet found; - for (auto & i : refsSink.getResult()) { + for (auto & i : getResult()) { auto j = backMap.find(i); assert(j != backMap.end()); found.insert(j->second); @@ -109,6 +101,31 @@ StorePathSet scanForReferences( } +std::pair scanForReferences( + const std::string & path, + const StorePathSet & refs) +{ + HashSink hashSink { htSHA256 }; + auto found = scanForReferences(hashSink, path, refs); + auto hash = hashSink.finish(); + return std::pair(found, hash); +} + +StorePathSet scanForReferences( + Sink & toTee, + const Path & path, + const StorePathSet & refs) +{ + PathRefScanSink refsSink = PathRefScanSink::fromPaths(refs); + TeeSink sink { refsSink, toTee }; + + /* Look for the hashes in the NAR dump of the path. */ + dumpPath(path, sink); + + return refsSink.getResultPaths(); +} + + RewritingSink::RewritingSink(const std::string & from, const std::string & to, Sink & nextSink) : from(from), to(to), nextSink(nextSink) { diff --git a/src/libstore/references.hh b/src/libstore/references.hh index a6119c861..6f381f96c 100644 --- a/src/libstore/references.hh +++ b/src/libstore/references.hh @@ -27,6 +27,19 @@ public: void operator () (std::string_view data) override; }; +class PathRefScanSink : public RefScanSink +{ + std::map backMap; + + PathRefScanSink(StringSet && hashes, std::map && backMap); + +public: + + static PathRefScanSink fromPaths(const StorePathSet & refs); + + StorePathSet getResultPaths(); +}; + struct RewritingSink : Sink { std::string from, to, prev; -- cgit v1.2.3