mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-22 14:06:16 +02:00
Merge pull request #9747 from awakesecurity/mz/fix-quadratic-splitString
Fix performance of builtins.substring for empty substrings
This commit is contained in:
commit
b2deff1947
3 changed files with 28 additions and 3 deletions
|
@ -3712,9 +3712,6 @@ static RegisterPrimOp primop_toString({
|
||||||
static void prim_substring(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
static void prim_substring(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
int start = state.forceInt(*args[0], pos, "while evaluating the first argument (the start offset) passed to builtins.substring");
|
int start = state.forceInt(*args[0], pos, "while evaluating the first argument (the start offset) passed to builtins.substring");
|
||||||
int len = state.forceInt(*args[1], pos, "while evaluating the second argument (the substring length) passed to builtins.substring");
|
|
||||||
NixStringContext context;
|
|
||||||
auto s = state.coerceToString(pos, *args[2], context, "while evaluating the third argument (the string) passed to builtins.substring");
|
|
||||||
|
|
||||||
if (start < 0)
|
if (start < 0)
|
||||||
state.debugThrowLastTrace(EvalError({
|
state.debugThrowLastTrace(EvalError({
|
||||||
|
@ -3722,6 +3719,22 @@ static void prim_substring(EvalState & state, const PosIdx pos, Value * * args,
|
||||||
.errPos = state.positions[pos]
|
.errPos = state.positions[pos]
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
int len = state.forceInt(*args[1], pos, "while evaluating the second argument (the substring length) passed to builtins.substring");
|
||||||
|
|
||||||
|
// Special-case on empty substring to avoid O(n) strlen
|
||||||
|
// This allows for the use of empty substrings to efficently capture string context
|
||||||
|
if (len == 0) {
|
||||||
|
state.forceValue(*args[2], pos);
|
||||||
|
if (args[2]->type() == nString) {
|
||||||
|
v.mkString("", args[2]->context());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NixStringContext context;
|
||||||
|
auto s = state.coerceToString(pos, *args[2], context, "while evaluating the third argument (the string) passed to builtins.substring");
|
||||||
|
|
||||||
v.mkString((unsigned int) start >= s->size() ? "" : s->substr(start, len), context);
|
v.mkString((unsigned int) start >= s->size() ? "" : s->substr(start, len), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
tests/functional/lang/eval-okay-substring-context.exp
Normal file
1
tests/functional/lang/eval-okay-substring-context.exp
Normal file
|
@ -0,0 +1 @@
|
||||||
|
"okay"
|
11
tests/functional/lang/eval-okay-substring-context.nix
Normal file
11
tests/functional/lang/eval-okay-substring-context.nix
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
with builtins;
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
s = "${builtins.derivation { name = "test"; builder = "/bin/sh"; system = "x86_64-linux"; }}";
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
if getContext s == getContext "${substring 0 0 s + unsafeDiscardStringContext s}"
|
||||||
|
then "okay"
|
||||||
|
else throw "empty substring should preserve context"
|
Loading…
Reference in a new issue