Skip to content

Commit 3ba2210

Browse files
committed
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
1 parent 0f85ef3 commit 3ba2210

File tree

1 file changed

+17
-21
lines changed

1 file changed

+17
-21
lines changed

src/libstore/outputs-spec.cc

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
#include <regex>
21
#include <nlohmann/json.hpp>
2+
#include <string_view>
33

4+
#include "nix/store/path.hh"
5+
#include "nix/store/store-dir-config.hh"
46
#include "nix/util/util.hh"
5-
#include "nix/util/regex-combinators.hh"
67
#include "nix/store/outputs-spec.hh"
7-
#include "nix/store/path-regex.hh"
88
#include "nix/util/strings-inline.hh"
99

1010
namespace nix {
@@ -19,31 +19,27 @@ bool OutputsSpec::contains(const std::string & outputName) const
1919
raw);
2020
}
2121

22-
static std::string outputSpecRegexStr = regex::either(regex::group(R"(\*)"), regex::group(regex::list(nameRegexStr)));
23-
2422
std::optional<OutputsSpec> OutputsSpec::parseOpt(std::string_view s)
2523
{
26-
static std::regex regex(std::string{outputSpecRegexStr});
27-
28-
std::cmatch match;
29-
if (!std::regex_match(s.cbegin(), s.cend(), match, regex))
24+
try {
25+
return parse(s);
26+
} catch (BadStorePathName &) {
3027
return std::nullopt;
31-
32-
if (match[1].matched)
33-
return {OutputsSpec::All{}};
34-
35-
if (match[2].matched)
36-
return OutputsSpec::Names{tokenizeString<StringSet>({match[2].first, match[2].second}, ",")};
37-
38-
assert(false);
28+
}
3929
}
4030

4131
OutputsSpec OutputsSpec::parse(std::string_view s)
4232
{
43-
std::optional spec = parseOpt(s);
44-
if (!spec)
45-
throw Error("invalid outputs specifier '%s'", s);
46-
return std::move(*spec);
33+
using namespace std::string_view_literals;
34+
35+
if (s == "*"sv)
36+
return OutputsSpec::All{};
37+
38+
auto names = splitString<StringSet>(s, ",");
39+
for (const auto & name : names)
40+
checkName(name);
41+
42+
return OutputsSpec::Names{std::move(names)};
4743
}
4844

4945
std::optional<std::pair<std::string_view, ExtendedOutputsSpec>> ExtendedOutputsSpec::parseOpt(std::string_view s)

0 commit comments

Comments
 (0)