treewide: wrap std::regex_error
otherwise lix may crash when e.g. nix search receives invalid regex. we now also give better error messages for regex errors during eval. fixes #803 Change-Id: Icc7c578ff488ba520efac5d898572ccf4486e9a8
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
#include "lix/libcmd/common-eval-args.hh"
|
||||
#include "lix/libexpr/attr-path.hh"
|
||||
#include "lix/libcmd/legacy.hh"
|
||||
#include "lix/libutil/regex.hh"
|
||||
#include "lix/libutil/shlex.hh"
|
||||
#include "nix-build.hh"
|
||||
#include "lix/libstore/temporary-dir.hh"
|
||||
@@ -31,7 +32,7 @@ using namespace std::string_literals;
|
||||
static void main_nix_build(AsyncIoRoot & aio, std::string programName, Strings argv)
|
||||
{
|
||||
auto dryRun = false;
|
||||
auto runEnv = std::regex_search(programName, std::regex("nix-shell$"));
|
||||
auto runEnv = std::regex_search(programName, regex::parse("nix-shell$"));
|
||||
auto pure = false;
|
||||
auto fromArgs = false;
|
||||
auto packages = false;
|
||||
@@ -68,7 +69,7 @@ static void main_nix_build(AsyncIoRoot & aio, std::string programName, Strings a
|
||||
script = argv.front();
|
||||
try {
|
||||
auto lines = tokenizeString<Strings>(readFile(script), "\n");
|
||||
if (std::regex_search(lines.front(), std::regex("^#!"))) {
|
||||
if (std::regex_search(lines.front(), regex::parse("^#!"))) {
|
||||
lines.pop_front();
|
||||
inShebang = true;
|
||||
savedArgs = {std::next(argv.begin()), argv.end()};
|
||||
@@ -76,7 +77,7 @@ static void main_nix_build(AsyncIoRoot & aio, std::string programName, Strings a
|
||||
for (auto line : lines) {
|
||||
line = chomp(line);
|
||||
std::smatch match;
|
||||
if (std::regex_match(line, match, std::regex("^#!\\s*nix-shell\\s+(.*)$")))
|
||||
if (std::regex_match(line, match, regex::parse("^#!\\s*nix-shell\\s+(.*)$")))
|
||||
for (const auto & word : shell_split(match[1].str()))
|
||||
argv.push_back(word);
|
||||
}
|
||||
@@ -148,14 +149,14 @@ static void main_nix_build(AsyncIoRoot & aio, std::string programName, Strings a
|
||||
// executes it unless it contains the string "perl" or "indir",
|
||||
// or (undocumented) argv[0] does not contain "perl". Exploit
|
||||
// the latter by doing "exec -a".
|
||||
if (std::regex_search(interpreter, std::regex("perl")))
|
||||
if (std::regex_search(interpreter, regex::parse("perl")))
|
||||
execArgs = "-a PERL";
|
||||
|
||||
std::ostringstream joined;
|
||||
for (const auto & i : savedArgs)
|
||||
joined << shellEscape(i) << ' ';
|
||||
|
||||
if (std::regex_search(interpreter, std::regex("ruby"))) {
|
||||
if (std::regex_search(interpreter, regex::parse("ruby"))) {
|
||||
// Hack for Ruby. Ruby also examines the shebang. It tries to
|
||||
// read the shebang to understand which packages to read from. Since
|
||||
// this is handled via nix-shell -p, we wrap our ruby script execution
|
||||
@@ -388,7 +389,7 @@ static void main_nix_build(AsyncIoRoot & aio, std::string programName, Strings a
|
||||
const auto & inputDrv = inputDrv0;
|
||||
if (std::all_of(envExclude.cbegin(), envExclude.cend(),
|
||||
[&](const std::string & exclude) {
|
||||
return !std::regex_search(store->printStorePath(inputDrv), std::regex(exclude));
|
||||
return !std::regex_search(store->printStorePath(inputDrv), regex::parse(exclude));
|
||||
}))
|
||||
{
|
||||
accumDerivedPath(makeConstantStorePathRef(inputDrv), inputNode);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "lix/libexpr/eval-settings.hh" // for defexpr
|
||||
#include "lix/libstore/temporary-dir.hh"
|
||||
#include "lix/libutil/async.hh"
|
||||
#include "lix/libutil/regex.hh"
|
||||
#include "lix/libutil/users.hh"
|
||||
#include "nix-channel.hh"
|
||||
|
||||
@@ -30,10 +31,10 @@ static void readChannels()
|
||||
|
||||
for (const auto & line : tokenizeString<std::vector<std::string>>(channelsFile, "\n")) {
|
||||
chomp(line);
|
||||
if (std::regex_search(line, std::regex("^\\s*\\#")))
|
||||
if (std::regex_search(line, regex::parse("^\\s*\\#")))
|
||||
continue;
|
||||
auto split = tokenizeString<std::vector<std::string>>(line, " ");
|
||||
auto url = std::regex_replace(split[0], std::regex("/*$"), "");
|
||||
auto url = std::regex_replace(split[0], regex::parse("/*$"), "");
|
||||
auto name = split.size() > 1 ? split[1] : std::string(baseNameOf(url));
|
||||
channels[name] = url;
|
||||
}
|
||||
@@ -52,9 +53,9 @@ static void writeChannels()
|
||||
// Adds a channel.
|
||||
static void addChannel(const std::string & url, const std::string & name)
|
||||
{
|
||||
if (!regex_search(url, std::regex("^(file|http|https)://")))
|
||||
if (!regex_search(url, regex::parse("^(file|http|https)://")))
|
||||
throw Error("invalid channel URL '%1%'", url);
|
||||
if (!regex_search(name, std::regex("^[a-zA-Z0-9_][a-zA-Z0-9_\\.-]*$")))
|
||||
if (!regex_search(name, regex::parse("^[a-zA-Z0-9_][a-zA-Z0-9_\\.-]*$")))
|
||||
throw Error("invalid channel identifier '%1%'", name);
|
||||
readChannels();
|
||||
channels[name] = url;
|
||||
@@ -101,7 +102,7 @@ static void update(AsyncIoRoot & aio, const StringSet & channelNames)
|
||||
auto cname = name;
|
||||
std::smatch match;
|
||||
auto urlBase = std::string(baseNameOf(url));
|
||||
if (std::regex_search(urlBase, match, std::regex("(-\\d.*)$")))
|
||||
if (std::regex_search(urlBase, match, regex::parse("(-\\d.*)$")))
|
||||
cname = cname + match.str(1);
|
||||
|
||||
std::string extraAttrs;
|
||||
@@ -125,7 +126,7 @@ static void update(AsyncIoRoot & aio, const StringSet & channelNames)
|
||||
url = result.effectiveUrl;
|
||||
|
||||
bool unpacked = false;
|
||||
if (std::regex_search(filename, std::regex("\\.tar\\.(gz|bz2|xz)$"))) {
|
||||
if (std::regex_search(filename, regex::parse("\\.tar\\.(gz|bz2|xz)$"))) {
|
||||
runProgram(settings.nixBinDir + "/nix-build", false, { "--no-out-link", "--expr", "import " + unpackChannelPath +
|
||||
"{ name = \"" + cname + "\"; channelName = \"" + name + "\"; src = builtins.storePath \"" + filename + "\"; }" });
|
||||
unpacked = true;
|
||||
@@ -234,8 +235,8 @@ static int main_nix_channel(AsyncIoRoot & aio, std::string programName, Strings
|
||||
name = args[1];
|
||||
} else {
|
||||
name = baseNameOf(url);
|
||||
name = std::regex_replace(name, std::regex("-unstable$"), "");
|
||||
name = std::regex_replace(name, std::regex("-stable$"), "");
|
||||
name = std::regex_replace(name, regex::parse("-unstable$"), "");
|
||||
name = std::regex_replace(name, regex::parse("-stable$"), "");
|
||||
}
|
||||
addChannel(url, name);
|
||||
}
|
||||
|
||||
@@ -9,12 +9,13 @@
|
||||
#include "lix/libstore/store-api.hh"
|
||||
#include "lix/libcmd/command.hh"
|
||||
#include "lix/libutil/async.hh"
|
||||
#include "lix/libutil/regex.hh"
|
||||
|
||||
#include <regex>
|
||||
|
||||
namespace nix {
|
||||
|
||||
static std::regex const identifierRegex("^[A-Za-z_][A-Za-z0-9_'-]*$");
|
||||
static std::regex const identifierRegex = regex::parse("^[A-Za-z_][A-Za-z0-9_'-]*$");
|
||||
static void warnInvalidNixIdentifier(const std::string & name)
|
||||
{
|
||||
std::smatch match;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "lix/libexpr/flake/flakeref.hh"
|
||||
#include "lix/libstore/store-api.hh"
|
||||
#include "lix/libutil/async.hh"
|
||||
#include "lix/libutil/regex.hh"
|
||||
#include "lix/libutil/url.hh"
|
||||
#include "lix/libutil/url-parts.hh"
|
||||
#include "lix/libfetchers/fetchers.hh"
|
||||
@@ -84,13 +85,13 @@ std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
|
||||
|
||||
static std::string fnRegex = "[0-9a-zA-Z-._~!$&'\"()*+,;=]+";
|
||||
|
||||
static std::regex pathUrlRegex(
|
||||
static std::regex pathUrlRegex = regex::parse(
|
||||
"(/?" + fnRegex + "(?:/" + fnRegex + ")*/?)"
|
||||
+ "(?:\\?(" + queryRegex + "))?"
|
||||
+ "(?:#(" + queryRegex + "))?",
|
||||
std::regex::ECMAScript);
|
||||
|
||||
static std::regex flakeShorthandRegex(
|
||||
static std::regex flakeShorthandRegex = regex::parse(
|
||||
flakeShorthandRegexS
|
||||
+ "(?:#(" + queryRegex + "))?",
|
||||
std::regex::ECMAScript);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "lix/libstore/path.hh"
|
||||
#include "lix/libstore/store-api.hh"
|
||||
#include "lix/libstore/path-with-outputs.hh"
|
||||
#include "lix/libutil/regex.hh"
|
||||
|
||||
#include <cstring>
|
||||
#include <regex>
|
||||
@@ -408,7 +409,7 @@ static std::string addToPath(const std::string & s1, const std::string & s2)
|
||||
}
|
||||
|
||||
|
||||
static std::regex attrRegex("[A-Za-z_][A-Za-z0-9-_+]*");
|
||||
static std::regex attrRegex = regex::parse("[A-Za-z_][A-Za-z0-9-_+]*");
|
||||
|
||||
|
||||
/* Evaluate value `v'. If it evaluates to a set of type `derivation',
|
||||
|
||||
+6
-21
@@ -17,6 +17,7 @@
|
||||
#include "lix/libexpr/value-to-xml.hh"
|
||||
#include "lix/libexpr/primops.hh"
|
||||
#include "lix/libfetchers/fetch-to-store.hh"
|
||||
#include "lix/libutil/regex.hh"
|
||||
#include "lix/libutil/types.hh"
|
||||
|
||||
#include <boost/container/small_vector.hpp>
|
||||
@@ -2570,7 +2571,7 @@ struct RegexCache
|
||||
if (it != cache.end())
|
||||
return it->second;
|
||||
keys.emplace_back(re);
|
||||
return cache.emplace(keys.back(), std::regex(keys.back(), std::regex::extended)).first->second;
|
||||
return cache.emplace(keys.back(), regex::parse(keys.back(), std::regex::extended)).first->second;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2609,16 +2610,8 @@ void prim_match(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||
(v.listElems()[i] = state.ctx.mem.allocValue())->mkString(match[i + 1].str());
|
||||
}
|
||||
|
||||
} catch (std::regex_error & e) { // NOLINT(lix-foreign-exceptions)
|
||||
if (e.code() == std::regex_constants::error_space) {
|
||||
// limit is _GLIBCXX_REGEX_STATE_LIMIT for libstdc++
|
||||
state.ctx.errors.make<EvalError>("memory limit exceeded by regular expression '%s'", re)
|
||||
.atPos(pos)
|
||||
.debugThrow();
|
||||
} else
|
||||
state.ctx.errors.make<EvalError>("invalid regular expression '%s'", re)
|
||||
.atPos(pos)
|
||||
.debugThrow();
|
||||
} catch (regex::Error & e) {
|
||||
state.ctx.errors.make<EvalError>(e.info()).atPos(pos).debugThrow();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2675,16 +2668,8 @@ void prim_split(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||
|
||||
assert(idx == 2 * len + 1);
|
||||
|
||||
} catch (std::regex_error & e) { // NOLINT(lix-foreign-exceptions)
|
||||
if (e.code() == std::regex_constants::error_space) {
|
||||
// limit is _GLIBCXX_REGEX_STATE_LIMIT for libstdc++
|
||||
state.ctx.errors.make<EvalError>("memory limit exceeded by regular expression '%s'", re)
|
||||
.atPos(pos)
|
||||
.debugThrow();
|
||||
} else
|
||||
state.ctx.errors.make<EvalError>("invalid regular expression '%s'", re)
|
||||
.atPos(pos)
|
||||
.debugThrow();
|
||||
} catch (regex::Error & e) {
|
||||
state.ctx.errors.make<EvalError>(e.info()).atPos(pos).debugThrow();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "lix/libfetchers/fetchers.hh"
|
||||
#include "lix/libstore/filetransfer.hh"
|
||||
#include "lix/libfetchers/registry.hh"
|
||||
#include "lix/libutil/regex.hh"
|
||||
#include "lix/libutil/url.hh"
|
||||
|
||||
#include <ctime>
|
||||
@@ -91,7 +92,7 @@ std::string fixURIForGit(std::string uri, EvalState & state)
|
||||
/* Detects scp-style uris (e.g. git@github.com:NixOS/nix) and fixes
|
||||
* them by removing the `:` and assuming a scheme of `ssh://`
|
||||
* */
|
||||
static std::regex scp_uri("([^/]*)@(.*):(.*)");
|
||||
static std::regex scp_uri = regex::parse("([^/]*)@(.*):(.*)");
|
||||
if (uri[0] != '/' && std::regex_match(uri, scp_uri))
|
||||
return fixURI(std::regex_replace(uri, scp_uri, "$1@$2/$3"), state, "ssh");
|
||||
else
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "lix/libfetchers/builtin-fetchers.hh"
|
||||
#include "lix/libstore/store-api.hh"
|
||||
#include "lix/libutil/async.hh"
|
||||
#include "lix/libutil/regex.hh"
|
||||
#include "lix/libutil/types.hh"
|
||||
#include "lix/libutil/url-parts.hh"
|
||||
#include "lix/libutil/git.hh"
|
||||
@@ -25,7 +26,7 @@ struct DownloadUrl
|
||||
|
||||
// A github, gitlab, or sourcehut host
|
||||
const static std::string hostRegexS = "[a-zA-Z0-9.-]*"; // FIXME: check
|
||||
std::regex hostRegex(hostRegexS, std::regex::ECMAScript);
|
||||
std::regex hostRegex = regex::parse(hostRegexS, std::regex::ECMAScript);
|
||||
|
||||
struct GitArchiveInputScheme : InputScheme
|
||||
{
|
||||
@@ -448,7 +449,7 @@ struct SourceHutInputScheme : GitArchiveInputScheme
|
||||
} else {
|
||||
refUri = fmt("refs/(heads|tags)/%s", ref);
|
||||
}
|
||||
std::regex refRegex(refUri);
|
||||
std::regex refRegex = regex::parse(refUri);
|
||||
|
||||
auto file = store->toRealPath(
|
||||
TRY_AWAIT(downloadFile(store, fmt("%s/info/refs", base_url), "source", false, headers))
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#include "lix/libfetchers/fetchers.hh"
|
||||
#include "lix/libfetchers/builtin-fetchers.hh"
|
||||
#include "lix/libutil/regex.hh"
|
||||
#include "lix/libutil/url-parts.hh"
|
||||
#include "lix/libstore/path.hh"
|
||||
|
||||
namespace nix::fetchers {
|
||||
|
||||
std::regex flakeRegex("[a-zA-Z][a-zA-Z0-9_-]*", std::regex::ECMAScript);
|
||||
std::regex flakeRegex = regex::parse("[a-zA-Z][a-zA-Z0-9_-]*", std::regex::ECMAScript);
|
||||
|
||||
struct IndirectInputScheme : InputScheme
|
||||
{
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "lix/libstore/fs-accessor.hh"
|
||||
#include "lix/libstore/nar-info.hh"
|
||||
#include "lix/libutil/json.hh"
|
||||
#include "lix/libutil/regex.hh"
|
||||
#include "lix/libutil/result.hh"
|
||||
#include "lix/libutil/sync.hh"
|
||||
#include "lix/libstore/remote-fs-accessor.hh"
|
||||
@@ -213,8 +214,8 @@ try {
|
||||
upsertFile(key, json.dump(), "application/json");
|
||||
};
|
||||
|
||||
std::regex regex1("^[0-9a-f]{2}$");
|
||||
std::regex regex2("^[0-9a-f]{38}\\.debug$");
|
||||
std::regex regex1 = regex::parse("^[0-9a-f]{2}$");
|
||||
std::regex regex2 = regex::parse("^[0-9a-f]{38}\\.debug$");
|
||||
|
||||
for (auto & [s1, s1Inode] : buildIdDir->contents) {
|
||||
auto dir = std::get_if<nar_index::Directory>(&s1Inode);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "lix/libstore/path-references.hh"
|
||||
#include "lix/libutil/archive.hh"
|
||||
#include "lix/libstore/daemon.hh"
|
||||
#include "lix/libutil/regex.hh"
|
||||
#include "lix/libutil/result.hh"
|
||||
#include "lix/libutil/topo-sort.hh"
|
||||
#include "lix/libutil/json.hh"
|
||||
@@ -572,7 +573,7 @@ try {
|
||||
throw BuildError("odd number of tokens in 'exportReferencesGraph': '%1%'", s);
|
||||
for (Strings::iterator i = ss.begin(); i != ss.end(); ) {
|
||||
auto fileName = *i++;
|
||||
static std::regex regex("[A-Za-z_][A-Za-z0-9_.-]*");
|
||||
static std::regex regex = nix::regex::parse("[A-Za-z_][A-Za-z0-9_.-]*");
|
||||
if (!std::regex_match(fileName, regex))
|
||||
throw Error("invalid file name '%s' in 'exportReferencesGraph'", fileName);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "lix/libstore/globals.hh"
|
||||
#include "lix/libstore/store-api.hh"
|
||||
#include "lix/libstore/s3.hh"
|
||||
#include "lix/libutil/regex.hh"
|
||||
#include "lix/libutil/signals.hh"
|
||||
#include "lix/libutil/strings.hh"
|
||||
#include "lix/libutil/thread-name.hh"
|
||||
@@ -294,7 +295,7 @@ struct curlFileTransfer : public FileTransfer
|
||||
std::string line(static_cast<char *>(contents), realSize);
|
||||
printMsg(lvlVomit, "got header for '%s': %s", uri, trim(line));
|
||||
|
||||
static std::regex statusLine("HTTP/[^ ]+ +[0-9]+(.*)", std::regex::extended | std::regex::icase);
|
||||
static std::regex statusLine = regex::parse("HTTP/[^ ]+ +[0-9]+(.*)", std::regex::extended | std::regex::icase);
|
||||
if (std::smatch match; std::regex_match(line, match, statusLine)) {
|
||||
statusMsg = trim(match.str(1));
|
||||
} else {
|
||||
@@ -311,7 +312,7 @@ struct curlFileTransfer : public FileTransfer
|
||||
|
||||
else if (name == "link" || name == "x-amz-meta-link") {
|
||||
auto value = trim(line.substr(i + 1));
|
||||
static std::regex linkRegex("<([^>]*)>; rel=\"immutable\"", std::regex::extended | std::regex::icase);
|
||||
static std::regex linkRegex = regex::parse("<([^>]*)>; rel=\"immutable\"", std::regex::extended | std::regex::icase);
|
||||
if (std::smatch match; std::regex_match(value, match, linkRegex)) {
|
||||
result.immutableUrl = match.str(1);
|
||||
} else
|
||||
|
||||
+2
-1
@@ -9,6 +9,7 @@
|
||||
#include "lix/libutil/finally.hh"
|
||||
#include "lix/libutil/types.hh"
|
||||
#include "lix/libutil/unix-domain-socket.hh"
|
||||
#include "lix/libutil/regex.hh"
|
||||
#include "lix/libutil/strings.hh"
|
||||
#include "lix/libutil/thread-name.hh"
|
||||
|
||||
@@ -363,7 +364,7 @@ void LocalStore::findPlatformRoots(UncheckedRoots & unchecked)
|
||||
// non-Darwin, non-Linux platforms. Both major platforms have
|
||||
// platform-specific code in lix/libstore/platform/
|
||||
try {
|
||||
std::regex lsofRegex(R"(^n(/.*)$)");
|
||||
std::regex lsofRegex = regex::parse(R"(^n(/.*)$)");
|
||||
auto lsofLines =
|
||||
tokenizeString<std::vector<std::string>>(runProgram(LSOF, true, { "-n", "-w", "-F", "n" }), "\n");
|
||||
for (const auto & line : lsofLines) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "lix/libstore/names.hh"
|
||||
#include "lix/libutil/regex.hh"
|
||||
#include "lix/libutil/strings.hh"
|
||||
|
||||
#include <regex>
|
||||
@@ -47,7 +48,7 @@ bool DrvName::matches(const DrvName & n)
|
||||
if (name != "*") {
|
||||
if (!regex) {
|
||||
regex = std::make_unique<Regex>();
|
||||
regex->regex = std::regex(name, std::regex::extended);
|
||||
regex->regex = nix::regex::parse(name, std::regex::extended);
|
||||
}
|
||||
if (!std::regex_match(n.name, regex->regex)) return false;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "lix/libstore/outputs-spec.hh"
|
||||
#include "lix/libstore/path-regex.hh"
|
||||
#include "lix/libutil/json.hh"
|
||||
#include "lix/libutil/regex.hh"
|
||||
#include "lix/libutil/strings.hh"
|
||||
|
||||
namespace nix {
|
||||
@@ -28,7 +29,7 @@ static std::string outputSpecRegexStr =
|
||||
|
||||
std::optional<OutputsSpec> OutputsSpec::parseOpt(std::string_view s)
|
||||
{
|
||||
static std::regex regex(std::string { outputSpecRegexStr });
|
||||
static std::regex regex = nix::regex::parse(std::string { outputSpecRegexStr });
|
||||
|
||||
std::smatch match;
|
||||
std::string s2 { s }; // until some improves std::regex
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "lix/libstore/parsed-derivations.hh"
|
||||
#include "lix/libutil/async.hh"
|
||||
#include "lix/libutil/json.hh"
|
||||
#include "lix/libutil/regex.hh"
|
||||
#include "lix/libutil/strings.hh"
|
||||
|
||||
#include <regex>
|
||||
@@ -132,7 +133,7 @@ bool ParsedDerivation::useUidRange() const
|
||||
return getRequiredSystemFeatures().count("uid-range");
|
||||
}
|
||||
|
||||
static std::regex shVarName("[A-Za-z_][A-Za-z0-9_]*");
|
||||
static std::regex shVarName = regex::parse("[A-Za-z_][A-Za-z0-9_]*");
|
||||
|
||||
kj::Promise<Result<std::optional<JSON>>>
|
||||
ParsedDerivation::prepareStructuredAttrs(Store & store, const StorePathSet & inputPaths)
|
||||
|
||||
@@ -66,8 +66,8 @@ void LinuxLocalStore::findPlatformRoots(UncheckedRoots & unchecked)
|
||||
auto procDir = AutoCloseDir{opendir("/proc")};
|
||||
if (procDir) {
|
||||
struct dirent * ent;
|
||||
auto digitsRegex = std::regex(R"(^\d+$)");
|
||||
auto mapRegex = std::regex(R"(^\s*\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+(/\S+)\s*$)");
|
||||
auto digitsRegex = regex::parse(R"(^\d+$)");
|
||||
auto mapRegex = regex::parse(R"(^\s*\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+(/\S+)\s*$)");
|
||||
auto storePathRegex = regex::storePathRegex(config().storeDir);
|
||||
while (errno = 0, ent = readdir(procDir.get())) {
|
||||
checkInterrupt();
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "lix/libutil/url.hh"
|
||||
#include "lix/libutil/archive.hh"
|
||||
#include "lix/libstore/uds-remote-store.hh"
|
||||
#include "lix/libutil/regex.hh"
|
||||
#include "lix/libutil/signals.hh"
|
||||
#include "lix/libutil/strings.hh"
|
||||
// FIXME this should not be here, see TODO below on
|
||||
@@ -1568,7 +1569,7 @@ static std::string extractConnStr(const std::string &proto, const std::string &c
|
||||
{
|
||||
if (proto.rfind("ssh") != std::string::npos) {
|
||||
std::smatch result;
|
||||
std::regex v6AddrRegex("^((.*)@)?\\[(.*)\\]$");
|
||||
std::regex v6AddrRegex = regex::parse("^((.*)@)?\\[(.*)\\]$");
|
||||
|
||||
if (std::regex_match(connStr, result, v6AddrRegex)) {
|
||||
if (result[1].matched) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "lix/libutil/logging.hh"
|
||||
#include "regex.hh"
|
||||
#if __linux__
|
||||
|
||||
#include "lix/libutil/cgroup.hh"
|
||||
@@ -39,7 +40,7 @@ std::map<std::string, std::string> getCgroups(const Path & cgroupFile)
|
||||
std::map<std::string, std::string> cgroups;
|
||||
|
||||
for (auto & line : tokenizeString<std::vector<std::string>>(readFile(cgroupFile), "\n")) {
|
||||
static std::regex regex("([0-9]+):([^:]*):(.*)");
|
||||
static std::regex regex = nix::regex::parse("([0-9]+):([^:]*):(.*)");
|
||||
std::smatch match;
|
||||
if (!std::regex_match(line, match, regex))
|
||||
throw Error("invalid line '%s' in '%s'", line, cgroupFile);
|
||||
|
||||
+2
-1
@@ -1,4 +1,5 @@
|
||||
#include "lix/libutil/git.hh"
|
||||
#include "regex.hh"
|
||||
|
||||
#include <regex>
|
||||
|
||||
@@ -7,7 +8,7 @@ namespace git {
|
||||
|
||||
std::optional<LsRemoteRefLine> parseLsRemoteLine(std::string_view line)
|
||||
{
|
||||
const static std::regex line_regex("^(ref: *)?([^\\s]+)(?:\\t+(.*))?$");
|
||||
const static std::regex line_regex = regex::parse("^(ref: *)?([^\\s]+)(?:\\t+(.*))?$");
|
||||
std::match_results<std::string_view::const_iterator> match;
|
||||
if (!std::regex_match(line.cbegin(), line.cend(), match, line_regex))
|
||||
return std::nullopt;
|
||||
|
||||
+14
-2
@@ -1,3 +1,4 @@
|
||||
#include "regex.hh"
|
||||
#include <string>
|
||||
#include <regex>
|
||||
|
||||
@@ -7,13 +8,24 @@ template class std::basic_regex<char>;
|
||||
namespace nix::regex {
|
||||
std::string quoteRegexChars(const std::string & raw)
|
||||
{
|
||||
static auto specialRegex = std::regex(R"([.^$\\*+?()\[\]{}|])");
|
||||
static auto specialRegex = parse(R"([.^$\\*+?()\[\]{}|])");
|
||||
return std::regex_replace(raw, specialRegex, R"(\$&)");
|
||||
}
|
||||
|
||||
std::regex storePathRegex(const std::string & storeDir)
|
||||
{
|
||||
return std::regex(quoteRegexChars(storeDir) + R"(/[0-9a-z]+[0-9a-zA-Z\+\-\._\?=]*)");
|
||||
return parse(quoteRegexChars(storeDir) + R"(/[0-9a-z]+[0-9a-zA-Z\+\-\._\?=]*)");
|
||||
}
|
||||
|
||||
std::regex parse(std::string_view re, std::regex::flag_type flags)
|
||||
try {
|
||||
return std::regex(re.begin(), re.end(), flags); // NOLINT: lix-foreign-exceptions
|
||||
} catch (std::regex_error & e) { // NOLINT: lix-foreign-exceptions
|
||||
if (e.code() == std::regex_constants::error_space) {
|
||||
// limit is _GLIBCXX_REGEX_STATE_LIMIT for libstdc++
|
||||
throw Error("memory limit exceeded by regular expression '%s'", re);
|
||||
} else {
|
||||
throw Error("invalid regular expression '%s': %s", re, e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
#pragma once
|
||||
///@file
|
||||
|
||||
#include "error.hh"
|
||||
#include <string>
|
||||
#include <regex>
|
||||
|
||||
namespace nix::regex {
|
||||
class Error : public nix::Error
|
||||
{
|
||||
public:
|
||||
using nix::Error::Error;
|
||||
};
|
||||
|
||||
std::string quoteRegexChars(const std::string & raw);
|
||||
|
||||
std::regex storePathRegex(const std::string & storeDir);
|
||||
|
||||
std::regex parse(std::string_view re, std::regex::flag_type flags = std::regex::ECMAScript);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "lix/libutil/shlex.hh"
|
||||
#include "lix/libutil/regex.hh"
|
||||
#include "lix/libutil/strings.hh"
|
||||
|
||||
namespace nix {
|
||||
@@ -15,7 +16,7 @@ std::vector<std::string> shell_split(const std::string & input)
|
||||
return result;
|
||||
}
|
||||
|
||||
std::regex whitespace("^\\s+");
|
||||
std::regex whitespace = regex::parse("^\\s+");
|
||||
auto begin = inputTrimmed.cbegin();
|
||||
std::string currentToken;
|
||||
enum State { sBegin, sSingleQuote, sDoubleQuote };
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
#include <regex>
|
||||
|
||||
#include "lix/libutil/url-name.hh"
|
||||
#include "regex.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
static std::string const attributeNamePattern("[a-zA-Z0-9_-]+");
|
||||
static std::regex const lastAttributeRegex("(?:" + attributeNamePattern + "\\.)*(?!default)(" + attributeNamePattern +")(\\^.*)?");
|
||||
static std::regex const lastAttributeRegex = regex::parse("(?:" + attributeNamePattern + "\\.)*(?!default)(" + attributeNamePattern +")(\\^.*)?");
|
||||
static std::string const pathSegmentPattern("[a-zA-Z0-9_-]+");
|
||||
static std::regex const lastPathSegmentRegex(".*/(" + pathSegmentPattern +")");
|
||||
static std::regex const secondPathSegmentRegex("(?:" + pathSegmentPattern + ")/(" + pathSegmentPattern +")(?:/.*)?");
|
||||
static std::regex const gitProviderRegex("github|gitlab|sourcehut");
|
||||
static std::regex const gitSchemeRegex("git($|\\+.*)");
|
||||
static std::regex const defaultOutputRegex(".*\\.default($|\\^.*)");
|
||||
static std::regex const lastPathSegmentRegex = regex::parse(".*/(" + pathSegmentPattern +")");
|
||||
static std::regex const secondPathSegmentRegex = regex::parse("(?:" + pathSegmentPattern + ")/(" + pathSegmentPattern +")(?:/.*)?");
|
||||
static std::regex const gitProviderRegex = regex::parse("github|gitlab|sourcehut");
|
||||
static std::regex const gitSchemeRegex = regex::parse("git($|\\+.*)");
|
||||
static std::regex const defaultOutputRegex = regex::parse(".*\\.default($|\\^.*)");
|
||||
|
||||
std::optional<std::string> getNameFromURL(ParsedURL const & url)
|
||||
{
|
||||
|
||||
+7
-6
@@ -2,18 +2,19 @@
|
||||
#include "lix/libutil/url-parts.hh"
|
||||
#include "lix/libutil/split.hh"
|
||||
#include "lix/libutil/strings.hh"
|
||||
#include "regex.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
std::regex refRegex(refRegexS, std::regex::ECMAScript);
|
||||
std::regex badGitRefRegex(badGitRefRegexS, std::regex::ECMAScript);
|
||||
std::regex revRegex(revRegexS, std::regex::ECMAScript);
|
||||
std::regex flakeIdRegex(flakeIdRegexS, std::regex::ECMAScript);
|
||||
std::regex flakeShorthandRegex(flakeShorthandRegexS, std::regex::ECMAScript);
|
||||
std::regex refRegex = regex::parse(refRegexS, std::regex::ECMAScript);
|
||||
std::regex badGitRefRegex = regex::parse(badGitRefRegexS, std::regex::ECMAScript);
|
||||
std::regex revRegex = regex::parse(revRegexS, std::regex::ECMAScript);
|
||||
std::regex flakeIdRegex = regex::parse(flakeIdRegexS, std::regex::ECMAScript);
|
||||
std::regex flakeShorthandRegex = regex::parse(flakeShorthandRegexS, std::regex::ECMAScript);
|
||||
|
||||
ParsedURL parseURL(const std::string & url)
|
||||
{
|
||||
static std::regex uriRegex(
|
||||
static std::regex uriRegex = regex::parse(
|
||||
"((" + schemeRegex + "):"
|
||||
+ "(?:(?://(" + authorityRegex + ")(" + absPathRegex + "))|(/?" + pathRegex + ")))"
|
||||
+ "(?:\\?(" + queryRegex + "))?"
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "lix/libmain/common-args.hh"
|
||||
#include "lix/libstore/names.hh"
|
||||
#include "lix/libutil/json.hh"
|
||||
#include "lix/libutil/regex.hh"
|
||||
#include "lix/libutil/result.hh"
|
||||
#include "diff-closures.hh"
|
||||
|
||||
@@ -66,7 +67,7 @@ try {
|
||||
/* Strip the output name. Unfortunately this is ambiguous (we
|
||||
can't distinguish between output names like "bin" and
|
||||
version suffixes like "unstable"). */
|
||||
static std::regex regex("(.*)-([a-z]+|lib32|lib64)");
|
||||
static std::regex regex = regex::parse("(.*)-([a-z]+|lib32|lib64)");
|
||||
std::cmatch match;
|
||||
std::string name{path.name()};
|
||||
std::string_view const origName = path.name();
|
||||
|
||||
+2
-1
@@ -8,6 +8,7 @@
|
||||
#include "lix/libutil/archive.hh"
|
||||
#include "lix/libstore/builtins/buildenv.hh"
|
||||
#include "lix/libexpr/flake/flakeref.hh"
|
||||
#include "lix/libutil/regex.hh"
|
||||
#include "user-env.hh"
|
||||
#include "lix/libstore/profiles.hh"
|
||||
#include "lix/libstore/names.hh"
|
||||
@@ -196,7 +197,7 @@ public:
|
||||
} else if (store->isStorePath(s)) {
|
||||
res.push_back(s);
|
||||
} else {
|
||||
res.push_back(RegexPattern{s,std::regex(s, std::regex::extended | std::regex::icase)});
|
||||
res.push_back(RegexPattern{s, regex::parse(s, std::regex::extended | std::regex::icase)});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -11,6 +11,7 @@
|
||||
#include "lix/libexpr/attr-path.hh"
|
||||
#include "lix/libutil/hilite.hh"
|
||||
#include "lix/libutil/json.hh"
|
||||
#include "lix/libutil/regex.hh"
|
||||
#include "search.hh"
|
||||
|
||||
#include <regex>
|
||||
@@ -79,10 +80,10 @@ struct CmdSearch : InstallableCommand, MixJSON
|
||||
excludeRegexes.reserve(excludeRes.size());
|
||||
|
||||
for (auto & re : res)
|
||||
regexes.push_back(std::regex(re, std::regex::extended | std::regex::icase));
|
||||
regexes.push_back(nix::regex::parse(re, std::regex::extended | std::regex::icase));
|
||||
|
||||
for (auto & re : excludeRes)
|
||||
excludeRegexes.emplace_back(re, std::regex::extended | std::regex::icase);
|
||||
excludeRegexes.emplace_back(nix::regex::parse(re, std::regex::extended | std::regex::icase));
|
||||
|
||||
auto evaluator = getEvaluator();
|
||||
auto state = evaluator->begin(aio());
|
||||
|
||||
@@ -42,6 +42,17 @@ void ForeignExceptions::registerMatchers(ast_matchers::MatchFinder *Finder) {
|
||||
cxxThrowExpr(unless(anyOf(rethrowsAllowed, throwsAllowed)))
|
||||
.bind("throw"))),
|
||||
this);
|
||||
|
||||
// flag STL constructors/functions that have caused exception problems before.
|
||||
Finder->addMatcher(
|
||||
traverse(
|
||||
clang::TK_AsIs,
|
||||
cxxConstructExpr(
|
||||
hasDeclaration(cxxConstructorDecl(
|
||||
hasAncestor(cxxRecordDecl(hasName("std::basic_regex"))),
|
||||
unless(anyOf(isDefaultConstructor(), isCopyConstructor(), isMoveConstructor())))))
|
||||
.bind("bad-ctor")),
|
||||
this);
|
||||
}
|
||||
|
||||
void ForeignExceptions::check(
|
||||
@@ -64,6 +75,12 @@ void ForeignExceptions::check(
|
||||
"provide useful traces for async functions. Throw "
|
||||
"nix::ForeignException instead where possible.");
|
||||
}
|
||||
} else if (const auto *ctor = Result.Nodes.getNodeAs<CXXConstructExpr>("bad-ctor")) {
|
||||
diag(
|
||||
ctor->getLocation(),
|
||||
"%0 throws non-Lix exceptions. Ensure that they are caught and wrapped "
|
||||
"properly, ideally by wrapping the constructor invocation itself.")
|
||||
<< ctor->getConstructor()->getNameAsString();
|
||||
} else {
|
||||
llvm_unreachable("bad match");
|
||||
}
|
||||
|
||||
@@ -87,6 +87,26 @@ namespace nix {
|
||||
, type \
|
||||
)
|
||||
|
||||
#define ASSERT_TRACE1_PREFIX(args, type, message) \
|
||||
ASSERT_THROW( \
|
||||
std::string expr(args); \
|
||||
std::string name = expr.substr(0, expr.find(" ")); \
|
||||
try { \
|
||||
Value v = eval("builtins." args); \
|
||||
state.forceValueDeep(v); \
|
||||
} catch (BaseError & e) { \
|
||||
ASSERT_PRED2([](auto got, auto want) { return got.starts_with(want); }, \
|
||||
PrintToString(e.info().msg), \
|
||||
PrintToString(message)); \
|
||||
ASSERT_EQ(e.info().traces.size(), 1) << "while testing " args << std::endl << e.what(); \
|
||||
auto trace = e.info().traces.rbegin(); \
|
||||
ASSERT_EQ(PrintToString(trace->hint), \
|
||||
PrintToString(HintFmt("while calling the '%s' builtin", name))); \
|
||||
throw; \
|
||||
} \
|
||||
, type \
|
||||
)
|
||||
|
||||
#define ASSERT_TRACE2(args, type, message, context) \
|
||||
ASSERT_THROW( \
|
||||
std::string expr(args); \
|
||||
@@ -1112,9 +1132,10 @@ namespace nix {
|
||||
HintFmt("expected a string but found %s: %s", "a set", Uncolored("{ }")),
|
||||
HintFmt("while evaluating the second argument passed to builtins.match"));
|
||||
|
||||
ASSERT_TRACE1("match \"(.*\" \"\"",
|
||||
// explanation string may be platform dependent
|
||||
ASSERT_TRACE1_PREFIX("match \"(.*\" \"\"",
|
||||
EvalError,
|
||||
HintFmt("invalid regular expression '%s'", "(.*"));
|
||||
HintFmt("invalid regular expression '%s': ", "(.*"));
|
||||
|
||||
}
|
||||
|
||||
@@ -1130,9 +1151,10 @@ namespace nix {
|
||||
HintFmt("expected a string but found %s: %s", "a set", Uncolored("{ }")),
|
||||
HintFmt("while evaluating the second argument passed to builtins.split"));
|
||||
|
||||
ASSERT_TRACE1("split \"f(o*o\" \"1foo2\"",
|
||||
// explanation string may be platform dependent
|
||||
ASSERT_TRACE1_PREFIX("split \"f(o*o\" \"1foo2\"",
|
||||
EvalError,
|
||||
HintFmt("invalid regular expression '%s'", "f(o*o"));
|
||||
HintFmt("invalid regular expression '%s': ", "f(o*o"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include "lix/libutil/regex.hh"
|
||||
#include <regex>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
@@ -22,7 +23,7 @@ class StorePathTest : public LibStoreTest
|
||||
{
|
||||
};
|
||||
|
||||
static std::regex nameRegex { std::string { nameRegexStr } };
|
||||
static std::regex nameRegex = regex::parse(nameRegexStr);
|
||||
|
||||
#define TEST_DONT_PARSE(NAME, STR) \
|
||||
TEST_F(StorePathTest, bad_ ## NAME) { \
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "lix/libutil/hilite.hh"
|
||||
#include "lix/libutil/regex.hh"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
@@ -11,7 +12,7 @@ namespace nix {
|
||||
|
||||
TEST(hiliteMatches, simpleHighlight) {
|
||||
std::string str = "Hello, world!";
|
||||
std::regex re = std::regex("world");
|
||||
std::regex re = regex::parse("world");
|
||||
auto matches = std::vector(std::sregex_iterator(str.begin(), str.end(), re), std::sregex_iterator());
|
||||
ASSERT_STREQ(
|
||||
hiliteMatches(str, matches, "(", ")").c_str(),
|
||||
@@ -21,7 +22,7 @@ namespace nix {
|
||||
|
||||
TEST(hiliteMatches, multipleMatches) {
|
||||
std::string str = "Hello, world, world, world, world, world, world, Hello!";
|
||||
std::regex re = std::regex("world");
|
||||
std::regex re = regex::parse("world");
|
||||
auto matches = std::vector(std::sregex_iterator(str.begin(), str.end(), re), std::sregex_iterator());
|
||||
ASSERT_STREQ(
|
||||
hiliteMatches(str, matches, "(", ")").c_str(),
|
||||
@@ -31,8 +32,8 @@ namespace nix {
|
||||
|
||||
TEST(hiliteMatches, overlappingMatches) {
|
||||
std::string str = "world, Hello, world, Hello, world, Hello, world, Hello, world!";
|
||||
std::regex re = std::regex("Hello, world");
|
||||
std::regex re2 = std::regex("world, Hello");
|
||||
std::regex re = regex::parse("Hello, world");
|
||||
std::regex re2 = regex::parse("world, Hello");
|
||||
auto v = std::vector(std::sregex_iterator(str.begin(), str.end(), re), std::sregex_iterator());
|
||||
for(auto it = std::sregex_iterator(str.begin(), str.end(), re2); it != std::sregex_iterator(); ++it) {
|
||||
v.push_back(*it);
|
||||
@@ -46,10 +47,10 @@ namespace nix {
|
||||
TEST(hiliteMatches, complexOverlappingMatches) {
|
||||
std::string str = "legacyPackages.x86_64-linux.git-crypt";
|
||||
std::vector regexes = {
|
||||
std::regex("t-cry"),
|
||||
std::regex("ux\\.git-cry"),
|
||||
std::regex("git-c"),
|
||||
std::regex("pt"),
|
||||
regex::parse("t-cry"),
|
||||
regex::parse("ux\\.git-cry"),
|
||||
regex::parse("git-c"),
|
||||
regex::parse("pt"),
|
||||
};
|
||||
std::vector<std::smatch> matches;
|
||||
for(auto regex : regexes)
|
||||
|
||||
Reference in New Issue
Block a user