diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc index 773794ffc..dc4889dfd 100644 --- a/src/libstore/daemon.cc +++ b/src/libstore/daemon.cc @@ -432,19 +432,26 @@ static void performOp(TunnelLogger * logger, ref store, } auto dumpSource = sinkToSource([&](Sink & saved) { - TeeSource savedNARSource(from, saved); - RetrieveRegularNARSink savedRegular { saved }; - if (method == FileIngestionMethod::Recursive) { - /* Get the entire NAR dump from the client and save it to - a string so that we can pass it to - addToStoreFromDump(). */ + /* We parse the NAR dump through into `saved` unmodified, + so why all this extra work? We still parse the NAR so + that we aren't sending arbitrary data to `saved` + unwittingly`, and we know when the NAR ends so we don't + consume the rest of `from` and can't parse another + command. (We don't trust `addToStoreFromDump` to not + eagerly consume the entire stream it's given, past the + length of the Nar. */ + TeeSource savedNARSource(from, saved); ParseSink sink; /* null sink; just parse the NAR */ parseDump(sink, savedNARSource); - } else + } else { + /* Incrementally parse the NAR file, stripping the + metadata, and streaming the sole file we expect into + `saved`. */ + RetrieveRegularNARSink savedRegular { saved }; parseDump(savedRegular, from); - - if (!savedRegular.regular) throw Error("regular file expected"); + if (!savedRegular.regular) throw Error("regular file expected"); + } }); logger->startWork(); auto path = store->addToStoreFromDump(*dumpSource, baseName, method, hashAlgo);