Skip to content

Commit

Permalink
fix: dump.Print strck overflow error on print cyclic value
Browse files Browse the repository at this point in the history
  • Loading branch information
inhere committed Mar 30, 2022
1 parent 286e8ae commit 6551ca2
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 37 deletions.
20 changes: 19 additions & 1 deletion dump/_examples/demo.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
package main

import "github.com/gookit/goutil/dump"
import (
"time"

"github.com/gookit/goutil/dump"
)

// rum demo:
// go run ./dump/_examples/demo.go
func main() {
val := map[string]interface{}{
"bool": true,
"number": 1 + 1i,
"bytes": []byte{97, 98, 99},
"lines": "multiline string\nline two",
"slice": []interface{}{1, 2},
"time": time.Now(),
"struct": struct{ test int32 }{
test: 13,
},
}
val["slice"].([]interface{})[1] = val["slice"]
dump.P(val)
return
// dump.Config.ShowFile = true
// dump.Config.ShowMethod = true
otherFunc()
Expand Down
34 changes: 34 additions & 0 deletions dump/_examples/demo_cyclic_ref.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package main

import (
"time"

"github.com/gookit/goutil/dump"
)

// rum demo:
// go run ./dump/_examples/demo_cyclic_ref.go
func main() {
a := map[string]interface{}{}
a["circular"] = map[string]interface{}{
"a": a,
}

// TIP: will stack overflow
// fmt.Println(a)
dump.V(a)

val := map[string]interface{}{
"bool": true,
"number": 1 + 1i,
"bytes": []byte{97, 98, 99},
"lines": "first line\nsecond line",
"slice": []interface{}{1, 2},
"time": time.Now(),
"struct": struct{ test int32 }{
test: 13,
},
}
val["slice"].([]interface{})[1] = val["slice"]
dump.P(val)
}
3 changes: 2 additions & 1 deletion dump/_examples/go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
module dump_example

go 1.13
go 1.14

require (
github.com/gookit/color v1.5.0
github.com/gookit/goutil v0.0.0-00010101000000-000000000000
github.com/kortschak/utter v1.0.1
github.com/kr/pretty v0.2.1
Expand Down
12 changes: 3 additions & 9 deletions dump/_examples/go.sum
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gookit/color v1.5.0 h1:1Opow3+BWDwqor78DcJkJCIwnkviFi+rrOANki9BUFw=
github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kortschak/utter v1.0.1 h1:AJVccwLrdrikvkH0aI5JKlzZIORLpfMeGBQ5tHfIXis=
github.com/kortschak/utter v1.0.1/go.mod h1:vSmSjbyrlKjjsL71193LmzBOKgwePk9DH6uFaWHIInc=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
Expand All @@ -14,15 +11,12 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
Expand Down
39 changes: 39 additions & 0 deletions dump/dump_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"testing"
"time"

"github.com/gookit/color"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -293,6 +294,44 @@ func TestFormat(t *testing.T) {
fmt.Println(s)
}

func TestPrint_over_max_depth(t *testing.T) {
a := map[string]interface{}{}
a["circular"] = map[string]interface{}{
"a": a,
}

// TIP: will stack overflow
// fmt.Println(a)

P(a)
s := Format(a)
assert.NotEmpty(t, s)
assert.Contains(t, s, "!OVER MAX DEPTH!")
}

func TestPrint_cyclic_slice(t *testing.T) {
a := map[string]interface{}{
"bool": true,
"number": 1 + 1i,
"bytes": []byte{97, 98, 99},
"lines": "first line\nsecond line",
"slice": []interface{}{1, 2},
"time": time.Now(),
"struct": struct{ test int32 }{
test: 13,
},
}
a["slice"].([]interface{})[1] = a["slice"]

// TIP: will stack overflow
// fmt.Println(a)

P(a)
s := Format(a)
assert.NotEmpty(t, s)
assert.Contains(t, s, "!CYCLIC REFERENCE!")
}

func newBuffer() *bytes.Buffer {
buf := new(bytes.Buffer)

Expand Down
59 changes: 45 additions & 14 deletions dump/dumper.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ func (d *Dumper) printOne(v interface{}) {

func (d *Dumper) printRValue(t reflect.Type, v reflect.Value) {
// var isPtr bool
// if is an ptr, get real type and value
// if is a ptr, get real type and value
if t.Kind() == reflect.Ptr {
if v.IsNil() {
d.printf("%s<nil>,\n", t.String())
Expand All @@ -248,12 +248,18 @@ func (d *Dumper) printRValue(t reflect.Type, v reflect.Value) {
d.indentPrint(t.String(), "<nil>, #invalid\n")
}

// if v.CanAddr() && !d.checkCyclicRef(t, v) {
// return // don't print v again
// }

if d.curDepth > d.MaxDepth {
if !v.CanInterface() {
d.printf("%s,\n", v.String())
} else {
d.printf("%#v,\n", v.Interface())
}
// if !v.CanInterface() {
// d.printf("%s,\n", v.String())
// } else {
// // v.Interface() will stack overflow on cyclic refer
// d.printf("%#v,\n", v.Interface())
// }
d.printf("%s(!OVER MAX DEPTH!),\n", v.String())
return
}

Expand All @@ -277,6 +283,10 @@ func (d *Dumper) printRValue(t reflect.Type, v reflect.Value) {
case reflect.Complex64, reflect.Complex128:
d.printf("%#v\n", v.Complex())
case reflect.Slice, reflect.Array:
if v.CanAddr() && !d.checkCyclicRef(t, v) {
break // don't print v again
}

eleNum := v.Len()
lenTip := d.ColorTheme.lenTip("#len=" + strconv.Itoa(eleNum))

Expand All @@ -296,14 +306,8 @@ func (d *Dumper) printRValue(t reflect.Type, v reflect.Value) {

d.indentPrint("],\n")
case reflect.Struct:
if v.CanAddr() {
addr := v.UnsafeAddr()
vis := visit{addr, t}
if vd, ok := d.visited[vis]; ok && vd < d.MaxDepth {
d.indentPrint(t.String(), "{(!CYCLIC REFERENCE!)}\n")
break // don't print v again
}
d.visited[vis] = d.curDepth
if v.CanAddr() && !d.checkCyclicRef(t, v) {
break // don't print v again
}

d.indentPrint(d.ColorTheme.msType(t.String()), " {\n")
Expand Down Expand Up @@ -342,6 +346,11 @@ func (d *Dumper) printRValue(t reflect.Type, v reflect.Value) {
d.printf("%#v: ", key.Interface())
}

if mv.CanAddr() && !d.checkCyclicRef(mv.Type(), mv) {
d.advance(-1)
continue // don't print mv again
}

// print field value
d.msValue = true
d.printRValue(mv.Type(), mv)
Expand All @@ -352,6 +361,10 @@ func (d *Dumper) printRValue(t reflect.Type, v reflect.Value) {

d.indentPrint("},\n")
case reflect.Interface:
if v.CanAddr() && !d.checkCyclicRef(t, v) {
break // don't print v again
}

switch e := v.Elem(); {
case e.Kind() == reflect.Invalid:
d.indentPrint("nil,\n")
Expand All @@ -371,6 +384,10 @@ func (d *Dumper) printRValue(t reflect.Type, v reflect.Value) {
case reflect.Invalid:
d.indentPrint(t.String(), "(nil),\n")
default:
if v.CanAddr() && !d.checkCyclicRef(t, v) {
break // don't print v again
}

if v.CanInterface() {
d.printf("%s(%#v),\n", t.String(), v.Interface())
} else {
Expand All @@ -379,6 +396,20 @@ func (d *Dumper) printRValue(t reflect.Type, v reflect.Value) {
}
}

func (d *Dumper) checkCyclicRef(t reflect.Type, v reflect.Value) (goon bool) {
addr := v.UnsafeAddr()
vis := visit{addr, t}

if vd, ok := d.visited[vis]; ok && vd < d.MaxDepth {
d.indentPrint(t.String(), "{(!CYCLIC REFERENCE!)}\n")
return false // don't print v again
}

// record
d.visited[vis] = d.curDepth
return true
}

func (d *Dumper) print(v ...interface{}) {
if d.NoColor {
_, _ = fmt.Fprint(d.Output, v...)
Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ require (
github.com/gookit/color v1.5.0
github.com/mattn/go-isatty v0.0.14
github.com/mitchellh/go-homedir v1.1.0
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/stretchr/testify v1.7.1
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c
Expand Down
12 changes: 1 addition & 11 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,24 +1,14 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gookit/color v1.5.0 h1:1Opow3+BWDwqor78DcJkJCIwnkviFi+rrOANki9BUFw=
github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
Expand Down

0 comments on commit 6551ca2

Please sign in to comment.