From 3ba221025f3d5e78e5f5fde22d704b403f2090e9 Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman Date: Mon, 13 Oct 2025 23:50:58 +0300 Subject: [PATCH] libstore/outputs-spec: Drop usage of std::regex std::regex is a really bad tool for parsing things, since it tends to overflow the stack pretty badly. See the build failure under ASan in [^]. [^]: https://hydra.nixos.org/build/310077167/nixlog/5 --- src/libstore/outputs-spec.cc | 38 ++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/src/libstore/outputs-spec.cc b/src/libstore/outputs-spec.cc index aacc964cd..622df5fc3 100644 --- a/src/libstore/outputs-spec.cc +++ b/src/libstore/outputs-spec.cc @@ -1,10 +1,10 @@ -#include #include +#include +#include "nix/store/path.hh" +#include "nix/store/store-dir-config.hh" #include "nix/util/util.hh" -#include "nix/util/regex-combinators.hh" #include "nix/store/outputs-spec.hh" -#include "nix/store/path-regex.hh" #include "nix/util/strings-inline.hh" namespace nix { @@ -19,31 +19,27 @@ bool OutputsSpec::contains(const std::string & outputName) const raw); } -static std::string outputSpecRegexStr = regex::either(regex::group(R"(\*)"), regex::group(regex::list(nameRegexStr))); - std::optional OutputsSpec::parseOpt(std::string_view s) { - static std::regex regex(std::string{outputSpecRegexStr}); - - std::cmatch match; - if (!std::regex_match(s.cbegin(), s.cend(), match, regex)) + try { + return parse(s); + } catch (BadStorePathName &) { return std::nullopt; - - if (match[1].matched) - return {OutputsSpec::All{}}; - - if (match[2].matched) - return OutputsSpec::Names{tokenizeString({match[2].first, match[2].second}, ",")}; - - assert(false); + } } OutputsSpec OutputsSpec::parse(std::string_view s) { - std::optional spec = parseOpt(s); - if (!spec) - throw Error("invalid outputs specifier '%s'", s); - return std::move(*spec); + using namespace std::string_view_literals; + + if (s == "*"sv) + return OutputsSpec::All{}; + + auto names = splitString(s, ","); + for (const auto & name : names) + checkName(name); + + return OutputsSpec::Names{std::move(names)}; } std::optional> ExtendedOutputsSpec::parseOpt(std::string_view s)