From 23a97b0079cfe1090dd284d98e01600c7abe1dee Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 17 Feb 2021 16:13:24 +0100 Subject: [PATCH] Use Boost's regex implementation instead of libstdc++'s The latter runs in unbounded stack space so it crashes on large inputs. Fixes #4550. --- flake.nix | 2 +- src/libutil/regex.hh | 6 ++++++ src/nix/develop.cc | 21 ++++++++++----------- src/nix/local.mk | 2 +- 4 files changed, 18 insertions(+), 13 deletions(-) create mode 100644 src/libutil/regex.hh diff --git a/flake.nix b/flake.nix index 8c60934e6..e86bdfcb0 100644 --- a/flake.nix +++ b/flake.nix @@ -135,7 +135,7 @@ # Copy libboost_context so we don't get all of Boost in our closure. # https://github.com/NixOS/nixpkgs/issues/45462 mkdir -p $out/lib - cp -pd ${boost}/lib/{libboost_context*,libboost_thread*,libboost_system*} $out/lib + cp -pd ${boost}/lib/{libboost_context*,libboost_thread*,libboost_system*,libboost_regex*} $out/lib rm -f $out/lib/*.a ${lib.optionalString stdenv.isLinux '' chmod u+w $out/lib/*.so.* diff --git a/src/libutil/regex.hh b/src/libutil/regex.hh new file mode 100644 index 000000000..c5a24aaa8 --- /dev/null +++ b/src/libutil/regex.hh @@ -0,0 +1,6 @@ +#pragma once + +#include + +namespace regex = boost; + diff --git a/src/nix/develop.cc b/src/nix/develop.cc index 3c44fdb0e..f52306680 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -6,8 +6,7 @@ #include "derivations.hh" #include "affinity.hh" #include "progress-bar.hh" - -#include +#include "regex.hh" using namespace nix; @@ -64,42 +63,42 @@ BuildEnvironment readEnvironment(const Path & path) static std::string indexedArrayRegex = R"re((?:\(( *\[[0-9]+\]="(?:[^"\\]|\\.)*")*\)))re"; - static std::regex declareRegex( + static regex::regex declareRegex( "^declare -a?x (" + varNameRegex + ")(=(" + dquotedStringRegex + "|" + indexedArrayRegex + "))?\n"); - static std::regex varRegex( + static regex::regex varRegex( "^(" + varNameRegex + ")=(" + simpleStringRegex + "|" + squotedStringRegex + "|" + indexedArrayRegex + ")\n"); /* Note: we distinguish between an indexed and associative array using the space before the closing parenthesis. Will undoubtedly regret this some day. */ - static std::regex assocArrayRegex( + static regex::regex assocArrayRegex( "^(" + varNameRegex + ")=" + R"re((?:\(( *\[[^\]]+\]="(?:[^"\\]|\\.)*")* *\)))re" + "\n"); - static std::regex functionRegex( + static regex::regex functionRegex( "^" + varNameRegex + " \\(\\) *\n"); while (pos != file.end()) { - std::smatch match; + regex::smatch match; - if (std::regex_search(pos, file.cend(), match, declareRegex, std::regex_constants::match_continuous)) { + if (regex::regex_search(pos, file.cend(), match, declareRegex, regex::regex_constants::match_continuous)) { pos = match[0].second; exported.insert(match[1]); } - else if (std::regex_search(pos, file.cend(), match, varRegex, std::regex_constants::match_continuous)) { + else if (regex::regex_search(pos, file.cend(), match, varRegex, regex::regex_constants::match_continuous)) { pos = match[0].second; res.env.insert({match[1], Var { .exported = exported.count(match[1]) > 0, .quoted = match[2] }}); } - else if (std::regex_search(pos, file.cend(), match, assocArrayRegex, std::regex_constants::match_continuous)) { + else if (regex::regex_search(pos, file.cend(), match, assocArrayRegex, regex::regex_constants::match_continuous)) { pos = match[0].second; res.env.insert({match[1], Var { .associative = true, .quoted = match[2] }}); } - else if (std::regex_search(pos, file.cend(), match, functionRegex, std::regex_constants::match_continuous)) { + else if (regex::regex_search(pos, file.cend(), match, functionRegex, regex::regex_constants::match_continuous)) { res.bashFunctions = std::string(pos, file.cend()); break; } diff --git a/src/nix/local.mk b/src/nix/local.mk index 83b6dd08b..3751e9046 100644 --- a/src/nix/local.mk +++ b/src/nix/local.mk @@ -18,7 +18,7 @@ nix_CXXFLAGS += -I src/libutil -I src/libstore -I src/libfetchers -I src/libexpr nix_LIBS = libexpr libmain libfetchers libstore libutil libcmd -nix_LDFLAGS = -pthread $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) -llowdown +nix_LDFLAGS = -pthread $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) -llowdown -lboost_regex $(foreach name, \ nix-build nix-channel nix-collect-garbage nix-copy-closure nix-daemon nix-env nix-hash nix-instantiate nix-prefetch-url nix-shell nix-store, \