diff --git a/gnovm/pkg/gnolang/values_string.go b/gnovm/pkg/gnolang/values_string.go index b18bdb0dddc..18a1ece679f 100644 --- a/gnovm/pkg/gnolang/values_string.go +++ b/gnovm/pkg/gnolang/values_string.go @@ -12,11 +12,17 @@ type protectedStringer interface { ProtectedString(*seenValues) string } -// This indicates the maximum anticipated depth of the stack when printing a Value type. -const defaultSeenValuesSize = 32 +const ( + // defaultSeenValuesSize indicates the maximum anticipated depth of the stack when printing a Value type. + defaultSeenValuesSize = 32 + + // nestedLimit indicates the maximum nested level when printing a deeply recursive value. + nestedLimit = 10 +) type seenValues struct { values []Value + nc int // nested counter, to limit recursivity } func (sv *seenValues) Put(v Value) { @@ -46,7 +52,7 @@ func (sv *seenValues) Pop() { } func newSeenValues() *seenValues { - return &seenValues{values: make([]Value, 0, defaultSeenValuesSize)} + return &seenValues{values: make([]Value, 0, defaultSeenValuesSize), nc: nestedLimit} } func (v StringValue) String() string { @@ -74,6 +80,10 @@ func (av *ArrayValue) ProtectedString(seen *seenValues) string { return fmt.Sprintf("%p", av) } + seen.nc-- + if seen.nc < 0 { + return "..." + } seen.Put(av) defer seen.Pop() diff --git a/gnovm/tests/files/recurse1.gno b/gnovm/tests/files/recurse1.gno new file mode 100644 index 00000000000..1d5f1c7fc72 --- /dev/null +++ b/gnovm/tests/files/recurse1.gno @@ -0,0 +1,12 @@ +package main + +func main() { + var x interface{} + for i := 0; i < 10000; i++ { + x = [1]interface{}{x} + } + println(x) +} + +// Output: +// array[(array[(array[(array[(array[(array[(array[(array[(array[(array[(... [1]interface{})] [1]interface{})] [1]interface{})] [1]interface{})] [1]interface{})] [1]interface{})] [1]interface{})] [1]interface{})] [1]interface{})] [1]interface{})]