about summary refs log tree commit diff
path: root/src/libexpr/primops.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libexpr/primops.cc')
-rw-r--r--src/libexpr/primops.cc40
1 files changed, 24 insertions, 16 deletions
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 3b965f209bb2..4398cc951da2 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -18,6 +18,7 @@
 
 #include <algorithm>
 #include <cstring>
+#include <regex>
 #include <dlfcn.h>
 
 
@@ -427,9 +428,9 @@ static void prim_trace(EvalState & state, const Pos & pos, Value * * args, Value
 {
     state.forceValue(*args[0]);
     if (args[0]->type == tString)
-        printMsg(lvlError, format("trace: %1%") % args[0]->string.s);
+        printError(format("trace: %1%") % args[0]->string.s);
     else
-        printMsg(lvlError, format("trace: %1%") % *args[0]);
+        printError(format("trace: %1%") % *args[0]);
     state.forceValue(*args[1]);
     v = *args[1];
 }
@@ -1515,10 +1516,16 @@ static void prim_div(EvalState & state, const Pos & pos, Value * * args, Value &
     NixFloat f2 = state.forceFloat(*args[1], pos);
     if (f2 == 0) throw EvalError(format("division by zero, at %1%") % pos);
 
-    if (args[0]->type == tFloat || args[1]->type == tFloat)
+    if (args[0]->type == tFloat || args[1]->type == tFloat) {
         mkFloat(v, state.forceFloat(*args[0], pos) / state.forceFloat(*args[1], pos));
-    else
-        mkInt(v, state.forceInt(*args[0], pos) / state.forceInt(*args[1], pos));
+    } else {
+        NixInt i1 = state.forceInt(*args[0], pos);
+        NixInt i2 = state.forceInt(*args[1], pos);
+        /* Avoid division overflow as it might raise SIGFPE. */
+        if (i1 == std::numeric_limits<NixInt>::min() && i2 == -1)
+            throw EvalError(format("overflow in integer division, at %1%") % pos);
+        mkInt(v, i1 / i2);
+    }
 }
 
 
@@ -1618,25 +1625,26 @@ static void prim_hashString(EvalState & state, const Pos & pos, Value * * args,
    ‘null’ or a list containing substring matches. */
 static void prim_match(EvalState & state, const Pos & pos, Value * * args, Value & v)
 {
-    Regex regex(state.forceStringNoCtx(*args[0], pos), true);
+    std::regex regex(state.forceStringNoCtx(*args[0], pos), std::regex::extended);
 
     PathSet context;
-    string s = state.forceString(*args[1], context, pos);
+    const std::string str = state.forceString(*args[1], context, pos);
+
 
-    Regex::Subs subs;
-    if (!regex.matches(s, subs)) {
+    std::smatch match;
+    if (!std::regex_match(str, match, regex)) {
         mkNull(v);
         return;
     }
 
-    unsigned int len = subs.empty() ? 0 : subs.rbegin()->first + 1;
+    // the first match is the whole string
+    const size_t len = match.size() - 1;
     state.mkList(v, len);
-    for (unsigned int n = 0; n < len; ++n) {
-        auto i = subs.find(n);
-        if (i == subs.end())
-            mkNull(*(v.listElems()[n] = state.allocValue()));
+    for (size_t i = 0; i < len; ++i) {
+        if (!match[i+1].matched)
+            mkNull(*(v.listElems()[i] = state.allocValue()));
         else
-            mkString(*(v.listElems()[n] = state.allocValue()), i->second);
+            mkString(*(v.listElems()[i] = state.allocValue()), match[i + 1].str().c_str());
     }
 }
 
@@ -1769,7 +1777,7 @@ void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
     if (state.restricted && !expectedHash)
         throw Error(format("‘%1%’ is not allowed in restricted mode") % who);
 
-    Path res = makeDownloader()->downloadCached(state.store, url, unpack, name, expectedHash);
+    Path res = getDownloader()->downloadCached(state.store, url, unpack, name, expectedHash);
     mkString(v, res, PathSet({res}));
 }