guix-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

216/376: Handle cycles when printing a value


From: Ludovic Courtès
Subject: 216/376: Handle cycles when printing a value
Date: Wed, 28 Jan 2015 22:05:09 +0000

civodul pushed a commit to tag 1.8
in repository guix.

commit 022618c794f64ea354e7c9e166f3c8fc1654c470
Author: Eelco Dolstra <address@hidden>
Date:   Mon Sep 22 14:59:37 2014 +0200

    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>; }; }
---
 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 bd49cec..1dab5ce 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;
 }
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]