1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-28 05:21:16 +02:00

fix(libutil): apply only the specified filter to decompress archive

This patch makes `makeDecompressionSink` strip only a single layer
of compression specified via method. This fixes erroneous decompression
of doubly-compressed NARs fetched with curl.
This commit is contained in:
Sergei Zimmerman 2024-03-30 01:29:29 +03:00
parent 6d9bafb3b8
commit 500683a949
No known key found for this signature in database
GPG key ID: A9B0B557CA632325
3 changed files with 63 additions and 20 deletions

View file

@ -38,8 +38,10 @@ struct ArchiveDecompressionSource : Source
{
std::unique_ptr<TarArchive> archive = 0;
Source & src;
ArchiveDecompressionSource(Source & src)
std::optional<std::string> compressionMethod;
ArchiveDecompressionSource(Source & src, std::optional<std::string> compressionMethod = std::nullopt)
: src(src)
, compressionMethod(std::move(compressionMethod))
{
}
~ArchiveDecompressionSource() override {}
@ -47,7 +49,7 @@ struct ArchiveDecompressionSource : Source
{
struct archive_entry * ae;
if (!archive) {
archive = std::make_unique<TarArchive>(src, true);
archive = std::make_unique<TarArchive>(src, /*raw*/ true, compressionMethod);
this->archive->check(archive_read_next_header(this->archive->archive, &ae), "failed to read header (%s)");
if (archive_filter_count(this->archive->archive) < 2) {
throw CompressionError("input compression not recognized");
@ -218,8 +220,8 @@ std::unique_ptr<FinishSink> makeDecompressionSink(const std::string & method, Si
else if (method == "br")
return std::make_unique<BrotliDecompressionSink>(nextSink);
else
return sourceToSink([&](Source & source) {
auto decompressionSource = std::make_unique<ArchiveDecompressionSource>(source);
return sourceToSink([method, &nextSink](Source & source) {
auto decompressionSource = std::make_unique<ArchiveDecompressionSource>(source, method);
decompressionSource->drainInto(nextSink);
});
}