1
1
Fork 0
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:
Sergei Zimmerman 2025-11-22 17:49:32 +00:00 committed by GitHub
commit 8cdeab8f2e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 194 additions and 1 deletions

View file

@ -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())
recurse(*v2);
try {
recurse(*v2);
index++;
} catch (Error & e) {
state.addErrorTrace(e, "while evaluating list element at index %1%", index);
throw;
}
}
}(v);
}

View file

@ -16,6 +16,8 @@ json printValueAsJSON(
{
checkInterrupt();
auto _level = state.addCallDepth(pos);
if (strict)
state.forceValue(v, pos);

View 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

View 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"

View file

@ -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;

View 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"
)

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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