libutil: reject malformed nars harder with better errors

fixes #993

Change-Id: I56aff32498ecd32e65f1576661d5a15808a4439f
This commit is contained in:
eldritch horrors
2025-09-12 23:22:11 +02:00
parent 95d43d1e39
commit d90e4a6581
2 changed files with 25 additions and 14 deletions
+19 -14
View File
@@ -367,14 +367,20 @@ struct Parser
buffer.clear(); \
u; \
})
#define READ_STRING_LIMITED(limit) \
({ \
size_t len = FETCH_INT(size_t); \
co_yield WantBytes{len + (8 - len % 8) % 8}; \
StringSource src(std::string_view(buffer.data(), buffer.size())); \
auto str = readString(src, (limit)); \
buffer.clear(); \
std::move(str); \
#define READ_STRING_LIMITED(limit) \
({ \
size_t len = FETCH_INT(size_t); \
if (len > (limit)) { \
throw SerialisationError( \
"found malformed string tag. input may be a compressed NAR, which cannot be read " \
"directly" \
); \
} \
co_yield WantBytes{len + (8 - len % 8) % 8}; \
StringSource src(std::string_view(buffer.data(), buffer.size())); \
auto str = readString(src, (limit)); \
buffer.clear(); \
std::move(str); \
})
#define READ_STRING() READ_STRING_LIMITED(std::numeric_limits<size_t>::max())
#define READ_PADDING(size) \
@@ -487,14 +493,13 @@ struct Parser
std::string version;
try {
version = READ_STRING_LIMITED(narVersionMagic1.size());
if (version != narVersionMagic1) {
throw SerialisationError("bad NAR version tag");
}
co_yield parse();
} catch (SerialisationError & e) {
/* This generally means the integer at the start couldn't be
decoded. Ignore and throw the exception below. */
throw badArchive(fmt("input doesn't look like a Nix archive (%s)", e.info().msg.str()));
}
if (version != narVersionMagic1) {
throw badArchive("input doesn't look like a Nix archive");
}
co_yield parse();
}
#undef FETCH_INT
+6
View File
@@ -62,6 +62,12 @@ if nix-store --dump $storePath >/dev/full ; then
exit -1
fi
# compressed nars should cause a useful error message. we use ascii
# text input because the salient point is the initial length field.
echo 'not a real nar' > bad.nar
expect 1 nix nar ls bad.nar / 2>&1 | fgrep "doesn't look like a Nix archive (found malformed string tag"
# Test reading from remote nar listings if available
nix copy --to "file://$cacheDir?write-nar-listing=true" $storePath