mirror of
https://github.com/NixOS/nix.git
synced 2025-11-24 11:19:35 +01:00
Merge pull request #14613 from roberth/deepSeq-stack-overflow
`deepSeq`, json: handle stack overflow, report list index
This commit is contained in:
commit
8cdeab8f2e
10 changed files with 194 additions and 1 deletions
|
|
@ -2188,6 +2188,8 @@ void EvalState::forceValueDeep(Value & v)
|
|||
std::set<const Value *> seen;
|
||||
|
||||
[&, &state(*this)](this const auto & recurse, Value & v) {
|
||||
auto _level = state.addCallDepth(v.determinePos(noPos));
|
||||
|
||||
if (!seen.insert(&v).second)
|
||||
return;
|
||||
|
||||
|
|
@ -2214,8 +2216,15 @@ void EvalState::forceValueDeep(Value & v)
|
|||
}
|
||||
|
||||
else if (v.isList()) {
|
||||
size_t index = 0;
|
||||
for (auto v2 : v.listView())
|
||||
try {
|
||||
recurse(*v2);
|
||||
index++;
|
||||
} catch (Error & e) {
|
||||
state.addErrorTrace(e, "while evaluating list element at index %1%", index);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}(v);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ json printValueAsJSON(
|
|||
{
|
||||
checkInterrupt();
|
||||
|
||||
auto _level = state.addCallDepth(pos);
|
||||
|
||||
if (strict)
|
||||
state.forceValue(v, pos);
|
||||
|
||||
|
|
|
|||
25
tests/functional/lang/eval-fail-deepseq-list-attr.err.exp
Normal file
25
tests/functional/lang/eval-fail-deepseq-list-attr.err.exp
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
error:
|
||||
… while calling the 'deepSeq' builtin
|
||||
at /pwd/lang/eval-fail-deepseq-list-attr.nix:3:1:
|
||||
2|
|
||||
3| builtins.deepSeq [
|
||||
| ^
|
||||
4| 1
|
||||
|
||||
… while evaluating list element at index 1
|
||||
|
||||
… while evaluating the attribute 'b'
|
||||
at /pwd/lang/eval-fail-deepseq-list-attr.nix:7:5:
|
||||
6| a = 2;
|
||||
7| b = throw "error in attr in list element";
|
||||
| ^
|
||||
8| }
|
||||
|
||||
… while calling the 'throw' builtin
|
||||
at /pwd/lang/eval-fail-deepseq-list-attr.nix:7:9:
|
||||
6| a = 2;
|
||||
7| b = throw "error in attr in list element";
|
||||
| ^
|
||||
8| }
|
||||
|
||||
error: error in attr in list element
|
||||
10
tests/functional/lang/eval-fail-deepseq-list-attr.nix
Normal file
10
tests/functional/lang/eval-fail-deepseq-list-attr.nix
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Test that deepSeq reports list index and attribute name in error traces.
|
||||
|
||||
builtins.deepSeq [
|
||||
1
|
||||
{
|
||||
a = 2;
|
||||
b = throw "error in attr in list element";
|
||||
}
|
||||
3
|
||||
] "unexpected success"
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
error:
|
||||
… while calling the 'deepSeq' builtin
|
||||
at /pwd/lang/eval-fail-deepseq-stack-overflow.nix:8:1:
|
||||
7| in
|
||||
8| builtins.deepSeq reverseLinkedList (
|
||||
| ^
|
||||
9| throw "unexpected success; expected a controlled stack overflow instead"
|
||||
|
||||
… while evaluating the attribute 'tail'
|
||||
at /pwd/lang/eval-fail-deepseq-stack-overflow.nix:6:67:
|
||||
5| long = builtins.genList (x: x) 100000;
|
||||
6| reverseLinkedList = builtins.foldl' (tail: head: { inherit head tail; }) null long;
|
||||
| ^
|
||||
7| in
|
||||
|
||||
(9997 duplicate frames omitted)
|
||||
|
||||
… while evaluating the attribute 'head'
|
||||
at /pwd/lang/eval-fail-deepseq-stack-overflow.nix:6:62:
|
||||
5| long = builtins.genList (x: x) 100000;
|
||||
6| reverseLinkedList = builtins.foldl' (tail: head: { inherit head tail; }) null long;
|
||||
| ^
|
||||
7| in
|
||||
|
||||
error: stack overflow; max-call-depth exceeded
|
||||
at /pwd/lang/eval-fail-deepseq-stack-overflow.nix:5:28:
|
||||
4| let
|
||||
5| long = builtins.genList (x: x) 100000;
|
||||
| ^
|
||||
6| reverseLinkedList = builtins.foldl' (tail: head: { inherit head tail; }) null long;
|
||||
10
tests/functional/lang/eval-fail-deepseq-stack-overflow.nix
Normal file
10
tests/functional/lang/eval-fail-deepseq-stack-overflow.nix
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Test that deepSeq on a deeply nested structure produces a controlled
|
||||
# stack overflow error rather than a segfault.
|
||||
|
||||
let
|
||||
long = builtins.genList (x: x) 100000;
|
||||
reverseLinkedList = builtins.foldl' (tail: head: { inherit head tail; }) null long;
|
||||
in
|
||||
builtins.deepSeq reverseLinkedList (
|
||||
throw "unexpected success; expected a controlled stack overflow instead"
|
||||
)
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
error:
|
||||
… while evaluating the attribute 'outPath'
|
||||
at «nix-internal»/derivation-internal.nix:50:7:
|
||||
49| value = commonAttrs // {
|
||||
50| outPath = builtins.getAttr outputName strict;
|
||||
| ^
|
||||
51| drvPath = strict.drvPath;
|
||||
|
||||
… while calling the 'getAttr' builtin
|
||||
at «nix-internal»/derivation-internal.nix:50:17:
|
||||
49| value = commonAttrs // {
|
||||
50| outPath = builtins.getAttr outputName strict;
|
||||
| ^
|
||||
51| drvPath = strict.drvPath;
|
||||
|
||||
… while calling the 'derivationStrict' builtin
|
||||
at «nix-internal»/derivation-internal.nix:37:12:
|
||||
36|
|
||||
37| strict = derivationStrict drvAttrs;
|
||||
| ^
|
||||
38|
|
||||
|
||||
… while evaluating derivation 'test'
|
||||
whose name attribute is located at /pwd/lang/eval-fail-derivation-structuredAttrs-stack-overflow.nix:5:3
|
||||
|
||||
… while evaluating attribute 'nested' of derivation 'test'
|
||||
at /pwd/lang/eval-fail-derivation-structuredAttrs-stack-overflow.nix:9:3:
|
||||
8| __structuredAttrs = true;
|
||||
9| nested =
|
||||
| ^
|
||||
10| let
|
||||
|
||||
… while evaluating attribute 'tail'
|
||||
at /pwd/lang/eval-fail-derivation-structuredAttrs-stack-overflow.nix:12:71:
|
||||
11| long = builtins.genList (x: x) 100000;
|
||||
12| reverseLinkedList = builtins.foldl' (tail: head: { inherit head tail; }) null long;
|
||||
| ^
|
||||
13| in
|
||||
|
||||
(9994 duplicate frames omitted)
|
||||
|
||||
… while evaluating attribute 'head'
|
||||
at /pwd/lang/eval-fail-derivation-structuredAttrs-stack-overflow.nix:12:66:
|
||||
11| long = builtins.genList (x: x) 100000;
|
||||
12| reverseLinkedList = builtins.foldl' (tail: head: { inherit head tail; }) null long;
|
||||
| ^
|
||||
13| in
|
||||
|
||||
error: stack overflow; max-call-depth exceeded
|
||||
at /pwd/lang/eval-fail-derivation-structuredAttrs-stack-overflow.nix:12:66:
|
||||
11| long = builtins.genList (x: x) 100000;
|
||||
12| reverseLinkedList = builtins.foldl' (tail: head: { inherit head tail; }) null long;
|
||||
| ^
|
||||
13| in
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
# Test that derivations with __structuredAttrs and deeply nested structures
|
||||
# produce a controlled stack overflow error rather than a segfault.
|
||||
|
||||
derivation {
|
||||
name = "test";
|
||||
system = "x86_64-linux";
|
||||
builder = "/bin/sh";
|
||||
__structuredAttrs = true;
|
||||
nested =
|
||||
let
|
||||
long = builtins.genList (x: x) 100000;
|
||||
reverseLinkedList = builtins.foldl' (tail: head: { inherit head tail; }) null long;
|
||||
in
|
||||
reverseLinkedList;
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
error:
|
||||
… while calling the 'toJSON' builtin
|
||||
at /pwd/lang/eval-fail-toJSON-stack-overflow.nix:8:1:
|
||||
7| in
|
||||
8| builtins.toJSON reverseLinkedList
|
||||
| ^
|
||||
9|
|
||||
|
||||
… while evaluating attribute 'tail'
|
||||
at /pwd/lang/eval-fail-toJSON-stack-overflow.nix:6:67:
|
||||
5| long = builtins.genList (x: x) 100000;
|
||||
6| reverseLinkedList = builtins.foldl' (tail: head: { inherit head tail; }) null long;
|
||||
| ^
|
||||
7| in
|
||||
|
||||
(9997 duplicate frames omitted)
|
||||
|
||||
… while evaluating attribute 'head'
|
||||
at /pwd/lang/eval-fail-toJSON-stack-overflow.nix:6:62:
|
||||
5| long = builtins.genList (x: x) 100000;
|
||||
6| reverseLinkedList = builtins.foldl' (tail: head: { inherit head tail; }) null long;
|
||||
| ^
|
||||
7| in
|
||||
|
||||
error: stack overflow; max-call-depth exceeded
|
||||
at /pwd/lang/eval-fail-toJSON-stack-overflow.nix:6:62:
|
||||
5| long = builtins.genList (x: x) 100000;
|
||||
6| reverseLinkedList = builtins.foldl' (tail: head: { inherit head tail; }) null long;
|
||||
| ^
|
||||
7| in
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
# Test that toJSON on a deeply nested structure produces a controlled
|
||||
# stack overflow error rather than a segfault.
|
||||
|
||||
let
|
||||
long = builtins.genList (x: x) 100000;
|
||||
reverseLinkedList = builtins.foldl' (tail: head: { inherit head tail; }) null long;
|
||||
in
|
||||
builtins.toJSON reverseLinkedList
|
||||
Loading…
Add table
Add a link
Reference in a new issue