Skip to content

Commit

Permalink
Merge pull request #9508 from infinisil/revert-7762-boost-regex
Browse files Browse the repository at this point in the history
Revert "Switch from std::regex to boost::regex"
  • Loading branch information
roberth authored Dec 1, 2023
2 parents 4781e7f + 333ea68 commit 188c803
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 39 deletions.
22 changes: 7 additions & 15 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@

configureFlags =
lib.optionals stdenv.isLinux [
"--with-boost=${boost-nix}/lib"
"--with-boost=${boost}/lib"
"--with-sandbox-shell=${sh}/bin/busybox"
]
++ lib.optionals (stdenv.isLinux && !(isStatic && stdenv.system == "aarch64-linux")) [
Expand Down Expand Up @@ -210,7 +210,7 @@
version = libgit2.lastModifiedDate;
cmakeFlags = (attrs.cmakeFlags or []) ++ ["-DUSE_SSH=exec"];
}))
boost-nix
boost
lowdown-nix
libsodium
]
Expand Down Expand Up @@ -434,14 +434,14 @@

propagatedBuildInputs = propagatedDeps;

disallowedReferences = [ boost-nix ];
disallowedReferences = [ boost ];

preConfigure = lib.optionalString (! currentStdenv.hostPlatform.isStatic)
''
# 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-nix}/lib/{libboost_context*,libboost_thread*,libboost_system*,libboost_regex*} $out/lib
cp -pd ${boost}/lib/{libboost_context*,libboost_thread*,libboost_system*} $out/lib
rm -f $out/lib/*.a
${lib.optionalString currentStdenv.hostPlatform.isLinux ''
chmod u+w $out/lib/*.so.*
Expand All @@ -451,9 +451,9 @@
for LIB in $out/lib/*.dylib; do
chmod u+w $LIB
install_name_tool -id $LIB $LIB
install_name_tool -delete_rpath ${boost-nix}/lib/ $LIB || true
install_name_tool -delete_rpath ${boost}/lib/ $LIB || true
done
install_name_tool -change ${boost-nix}/lib/libboost_system.dylib $out/lib/libboost_system.dylib $out/lib/libboost_thread.dylib
install_name_tool -change ${boost}/lib/libboost_system.dylib $out/lib/libboost_system.dylib $out/lib/libboost_thread.dylib
''}
'';

Expand Down Expand Up @@ -481,13 +481,9 @@
''}
${lib.optionalString currentStdenv.isDarwin ''
install_name_tool \
-change ${boost-nix}/lib/libboost_context.dylib \
-change ${boost}/lib/libboost_context.dylib \
$out/lib/libboost_context.dylib \
$out/lib/libnixutil.dylib
install_name_tool \
-change ${boost-nix}/lib/libboost_regex.dylib \
$out/lib/libboost_regex.dylib \
$out/lib/libnixexpr.dylib
''}
'';

Expand All @@ -510,10 +506,6 @@
meta.mainProgram = "nix";
});

boost-nix = final.boost.override {
enableIcu = false;
};

lowdown-nix = with final; currentStdenv.mkDerivation rec {
name = "lowdown-0.9.0";

Expand Down
2 changes: 1 addition & 1 deletion src/libexpr/local.mk
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ libexpr_CXXFLAGS += -I src/libutil -I src/libstore -I src/libfetchers -I src/lib

libexpr_LIBS = libutil libstore libfetchers

libexpr_LDFLAGS += -lboost_context -lboost_regex -pthread
libexpr_LDFLAGS += -lboost_context -pthread
ifdef HOST_LINUX
libexpr_LDFLAGS += -ldl
endif
Expand Down
35 changes: 12 additions & 23 deletions src/libexpr/primops.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#include "primops.hh"

#include <boost/container/small_vector.hpp>
#include <boost/regex.hpp>
#include <nlohmann/json.hpp>

#include <sys/types.h>
Expand All @@ -26,6 +25,7 @@

#include <algorithm>
#include <cstring>
#include <regex>
#include <dlfcn.h>

#include <cmath>
Expand Down Expand Up @@ -3886,30 +3886,19 @@ static RegisterPrimOp primop_convertHash({
.fun = prim_convertHash,
});

// regex aliases, switch between boost and std
using regex = boost::regex;
using regex_error = boost::regex_error;
using cmatch = boost::cmatch;
using cregex_iterator = boost::cregex_iterator;
namespace regex_constants = boost::regex_constants;
// overloaded function alias
constexpr auto regex_match = [] (auto &&...args) {
return boost::regex_match(std::forward<decltype(args)>(args)...);
};

struct RegexCache
{
// TODO use C++20 transparent comparison when available
std::unordered_map<std::string_view, regex> cache;
std::unordered_map<std::string_view, std::regex> cache;
std::list<std::string> keys;

regex get(std::string_view re)
std::regex get(std::string_view re)
{
auto it = cache.find(re);
if (it != cache.end())
return it->second;
keys.emplace_back(re);
return cache.emplace(keys.back(), regex(keys.back(), regex::extended)).first->second;
return cache.emplace(keys.back(), std::regex(keys.back(), std::regex::extended)).first->second;
}
};

Expand All @@ -3929,8 +3918,8 @@ void prim_match(EvalState & state, const PosIdx pos, Value * * args, Value & v)
NixStringContext context;
const auto str = state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.match");

cmatch match;
if (!regex_match(str.begin(), str.end(), match, regex)) {
std::cmatch match;
if (!std::regex_match(str.begin(), str.end(), match, regex)) {
v.mkNull();
return;
}
Expand All @@ -3945,8 +3934,8 @@ void prim_match(EvalState & state, const PosIdx pos, Value * * args, Value & v)
(v.listElems()[i] = state.allocValue())->mkString(match[i + 1].str());
}

} catch (regex_error & e) {
if (e.code() == regex_constants::error_space) {
} catch (std::regex_error & e) {
if (e.code() == std::regex_constants::error_space) {
// limit is _GLIBCXX_REGEX_STATE_LIMIT for libstdc++
state.debugThrowLastTrace(EvalError({
.msg = hintfmt("memory limit exceeded by regular expression '%s'", re),
Expand Down Expand Up @@ -4009,8 +3998,8 @@ void prim_split(EvalState & state, const PosIdx pos, Value * * args, Value & v)
NixStringContext context;
const auto str = state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.split");

auto begin = cregex_iterator(str.begin(), str.end(), regex);
auto end = cregex_iterator();
auto begin = std::cregex_iterator(str.begin(), str.end(), regex);
auto end = std::cregex_iterator();

// Any matches results are surrounded by non-matching results.
const size_t len = std::distance(begin, end);
Expand Down Expand Up @@ -4049,8 +4038,8 @@ void prim_split(EvalState & state, const PosIdx pos, Value * * args, Value & v)

assert(idx == 2 * len + 1);

} catch (regex_error & e) {
if (e.code() == regex_constants::error_space) {
} catch (std::regex_error & e) {
if (e.code() == std::regex_constants::error_space) {
// limit is _GLIBCXX_REGEX_STATE_LIMIT for libstdc++
state.debugThrowLastTrace(EvalError({
.msg = hintfmt("memory limit exceeded by regular expression '%s'", re),
Expand Down
8 changes: 8 additions & 0 deletions src/libexpr/tests/primops.cc
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,14 @@ namespace nix {
ASSERT_THAT(*v.listElems()[0], IsStringEq("FOO"));
}

TEST_F(PrimOpTest, match5) {
// The regex "\\{}" is valid and matches the string "{}".
// Caused a regression before when trying to switch from std::regex to boost::regex.
// See https://github.com/NixOS/nix/pull/7762#issuecomment-1834303659
auto v = eval("builtins.match \"\\\\{}\" \"{}\"");
ASSERT_THAT(v, IsListOfSize(0));
}

TEST_F(PrimOpTest, attrNames) {
auto v = eval("builtins.attrNames { x = 1; y = 2; z = 3; a = 2; }");
ASSERT_THAT(v, IsListOfSize(4));
Expand Down

0 comments on commit 188c803

Please sign in to comment.