mirror of
https://github.com/NixOS/nix.git
synced 2025-11-24 11:19:35 +01:00
libexpr: fix stack overflow in toJSON on deeply nested structures
Similar to the deepSeq fix, toJSON on deeply nested structures caused an uncontrolled OS-level stack overflow. Fix by adding call depth tracking to printValueAsJSON.
This commit is contained in:
parent
a812b6c6e6
commit
c7e1c612eb
5 changed files with 109 additions and 0 deletions
|
|
@ -16,6 +16,8 @@ json printValueAsJSON(
|
||||||
{
|
{
|
||||||
checkInterrupt();
|
checkInterrupt();
|
||||||
|
|
||||||
|
auto _level = state.addCallDepth(pos);
|
||||||
|
|
||||||
if (strict)
|
if (strict)
|
||||||
state.forceValue(v, pos);
|
state.forceValue(v, pos);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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