From 7a05ed9c12288d05dec28c6fa4abcdef2bf68402 Mon Sep 17 00:00:00 2001 From: Samuel Connelly <140354451+myclevorname@users.noreply.github.com> Date: Fri, 3 Oct 2025 18:41:01 -0400 Subject: [PATCH] libutil: Throw if `str("contents")` not found This was broken in 7aa3e7e3a5281acf350eff0fe039656cd4986e2c (since 2.25). (cherry picked from commit 242f3625675cc06069edfd0936ad6f42acb068a8) --- src/libutil-tests/archive.cc | 47 ++++++++++++++++++ .../nars/invalid-tag-instead-of-contents.nar | Bin 0 -> 104 bytes src/libutil-tests/meson.build | 1 + src/libutil/archive.cc | 6 ++- 4 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 src/libutil-tests/archive.cc create mode 100644 src/libutil-tests/data/nars/invalid-tag-instead-of-contents.nar diff --git a/src/libutil-tests/archive.cc b/src/libutil-tests/archive.cc new file mode 100644 index 000000000..386f7b857 --- /dev/null +++ b/src/libutil-tests/archive.cc @@ -0,0 +1,47 @@ +#include "nix/util/archive.hh" +#include "nix/util/tests/characterization.hh" +#include "nix/util/tests/gmock-matchers.hh" + +#include + +namespace nix { + +namespace { + +class NarTest : public CharacterizationTest +{ + std::filesystem::path unitTestData = getUnitTestData() / "nars"; + +public: + std::filesystem::path goldenMaster(std::string_view testStem) const override + { + return unitTestData / (std::string(testStem) + ".nar"); + } +}; + +class InvalidNarTest : public NarTest, public ::testing::WithParamInterface> +{}; + +} // namespace + +TEST_P(InvalidNarTest, throwsErrorMessage) +{ + const auto & [name, message] = GetParam(); + readTest(name, [&](const std::string & narContents) { + ASSERT_THAT( + [&]() { + StringSource source{narContents}; + NullFileSystemObjectSink sink; + parseDump(sink, source); + }, + ::testing::ThrowsMessage(testing::HasSubstrIgnoreANSIMatcher(message))); + }); +} + +INSTANTIATE_TEST_SUITE_P( + NarTest, + InvalidNarTest, + ::testing::Values( + std::pair{"invalid-tag-instead-of-contents", "bad archive: expected tag 'contents', got 'AAAAAAAA'"})); + +} // namespace nix diff --git a/src/libutil-tests/data/nars/invalid-tag-instead-of-contents.nar b/src/libutil-tests/data/nars/invalid-tag-instead-of-contents.nar new file mode 100644 index 0000000000000000000000000000000000000000..80dbf5a12ff8cd03fb1cadcc8a827982d1f9d5aa GIT binary patch literal 104 zcmd;OfPlQr3f;t_5|HVR1lLL$}dVyFU?6TV&H)C9iafG IUlS@00Jy9R>;M1& literal 0 HcmV?d00001 diff --git a/src/libutil-tests/meson.build b/src/libutil-tests/meson.build index 0e2a2e468..ec235ae98 100644 --- a/src/libutil-tests/meson.build +++ b/src/libutil-tests/meson.build @@ -44,6 +44,7 @@ config_priv_h = configure_file( subdir('nix-meson-build-support/common') sources = files( + 'archive.cc', 'args.cc', 'base-n.cc', 'canon-path.cc', diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc index b978ac4db..3d96df75e 100644 --- a/src/libutil/archive.cc +++ b/src/libutil/archive.cc @@ -187,8 +187,10 @@ static void parse(FileSystemObjectSink & sink, Source & source, const CanonPath tag = getString(); } - if (tag == "contents") - parseContents(crf, source); + if (tag != "contents") + throw badArchive("expected tag 'contents', got '%s'", tag); + + parseContents(crf, source); expectTag(")"); });