diff options
author | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2014-09-22 14:59:37 +0200 |
---|---|---|
committer | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2014-09-22 16:05:00 +0200 |
commit | 022618c794f64ea354e7c9e166f3c8fc1654c470 (patch) | |
tree | 66fae354dd8b053af36e0452e76f0318cafa551b /src | |
parent | a54c263402cf140b6f91e26c02f13cbeeda76583 (diff) |
Handle cycles when printing a value
So this no longer crashes with a stack overflow:
nix-instantiate -E --eval 'let as = { x = as; }; in as'
Instead it prints:
{ x = { x = <CYCLE>; }; }
Diffstat (limited to 'src')
-rw-r--r-- | src/libexpr/eval.cc | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index bd49cec4f..1dab5ceff 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -38,8 +38,14 @@ void Bindings::sort() } -std::ostream & operator << (std::ostream & str, const Value & v) +static void printValue(std::ostream & str, std::set<const Value *> & seen, const Value & v) { + if (seen.find(&v) != seen.end()) { + str << "<CYCLE>"; + return; + } + seen.insert(&v); + switch (v.type) { case tInt: str << v.integer; @@ -69,15 +75,20 @@ std::ostream & operator << (std::ostream & str, const Value & v) Sorted sorted; foreach (Bindings::iterator, i, *v.attrs) sorted[i->name] = i->value; - foreach (Sorted::iterator, i, sorted) - str << i->first << " = " << *i->second << "; "; + for (auto & i : sorted) { + str << i.first << " = "; + printValue(str, seen, *i.second); + str << "; "; + } str << "}"; break; } case tList: str << "[ "; - for (unsigned int n = 0; n < v.list.length; ++n) - str << *v.list.elems[n] << " "; + for (unsigned int n = 0; n < v.list.length; ++n) { + printValue(str, seen, *v.list.elems[n]); + str << " "; + } str << "]"; break; case tThunk: @@ -96,6 +107,13 @@ std::ostream & operator << (std::ostream & str, const Value & v) default: throw Error("invalid value"); } +} + + +std::ostream & operator << (std::ostream & str, const Value & v) +{ + std::set<const Value *> seen; + printValue(str, seen, v); return str; } |