From eafc75b9e911b0969b89e4cb8bed809df75b03b7 Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Mon, 3 Mar 2025 20:48:59 +0100 Subject: [PATCH] libutil: handle nar header in Parser as well that'll make adding more Parser users a lot easier. Change-Id: I88032d84b178c67896e930e275b9affe1e46ba83 --- lix/libutil/archive.cc | 46 +++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/lix/libutil/archive.cc b/lix/libutil/archive.cc index 662054d79..cddf84943 100644 --- a/lix/libutil/archive.cc +++ b/lix/libutil/archive.cc @@ -347,12 +347,10 @@ struct Parser std::vector & buffer; - Generator parse() - { - // these macros purposely duplicate parts of the wire protocol, - // but in such a way that doing it *wrong* will definitely make - // tests fail. we could also duplicate them completely, but not - // doing so ensures that we're the inverse of dump at all times + // these macros purposely duplicate parts of the wire protocol, + // but in such a way that doing it *wrong* will definitely make + // tests fail. we could also duplicate them completely, but not + // doing so ensures that we're the inverse of dump at all times #define FETCH_U64() \ ({ \ co_yield WantBytes{8}; \ @@ -365,15 +363,16 @@ struct Parser buffer.clear(); \ u; \ }) -#define READ_STRING() \ +#define READ_STRING_LIMITED(limit) \ ({ \ uint64_t len = FETCH_U64(); \ co_yield WantBytes{len + (8 - len % 8) % 8}; \ StringSource src(std::string_view(buffer.data(), buffer.size())); \ - auto str = readString(src); \ + auto str = readString(src, (limit)); \ buffer.clear(); \ std::move(str); \ }) +#define READ_STRING() READ_STRING_LIMITED(std::numeric_limits::max()) #define READ_PADDING(size) \ do { \ if ((size) % 8) { \ @@ -391,6 +390,8 @@ struct Parser } \ } while (0) + Generator parse() + { EXPECT("(", "open"); EXPECT("type", "type"); @@ -484,13 +485,29 @@ struct Parser } EXPECT(")", "close"); + } + + Generator parseRoot() + { + std::string version; + try { + version = READ_STRING_LIMITED(narVersionMagic1.size()); + } catch (SerialisationError & e) { + /* This generally means the integer at the start couldn't be + decoded. Ignore and throw the exception below. */ + } + if (version != narVersionMagic1) { + throw badArchive("input doesn't look like a Nix archive"); + } + co_yield parse(); + } #undef FETCH_U64 #undef READ_U64 #undef READ_STRING +#undef READ_STRING_LIMITED #undef READ_PADDING #undef EXPECT - } }; struct SyncParser @@ -501,7 +518,7 @@ struct SyncParser Generator parse() { Parser parser{buffer}; - auto stream = parser.parse(); + auto stream = parser.parseRoot(); co_yield parse(stream); } @@ -568,15 +585,6 @@ struct SyncParser Generator parse(Source & source) { - std::string version; - try { - version = readString(source, narVersionMagic1.size()); - } catch (SerialisationError & e) { - /* This generally means the integer at the start couldn't be - decoded. Ignore and throw the exception below. */ - } - if (version != narVersionMagic1) - throw badArchive("input doesn't look like a Nix archive"); SyncParser p{source}; co_yield p.parse(); }