proc/variables: fix infinite recursion with pointer loop (#725)

loadValue didn't react correctly to pointer loops going through
slice -> interface{} -> slice or pointer -> interface{} -> pointer.
This commit is contained in:
Alessandro Arzilli 2017-02-10 01:26:38 +01:00 committed by Derek Parker
parent ce01a67d8b
commit fc0d40144a
4 changed files with 27 additions and 9 deletions

@ -212,6 +212,14 @@ func main() {
ninf := math.Inf(-1)
nan := math.NaN()
var iface6 interface{}
var ptrinf *interface{}
iface6 = &ptrinf
ptrinf = &iface6
sliceinf := make([]interface{}, 1)
sliceinf[0] = sliceinf
var amb1 = 1
runtime.Breakpoint()
for amb1 := 0; amb1 < 10; amb1++ {

@ -1440,14 +1440,17 @@ func TestIssue305(t *testing.T) {
})
}
func TestIssue341(t *testing.T) {
// pointer loop through map entries
func TestPointerLoops(t *testing.T) {
// Pointer loops through map entries, pointers and slices
// Regression test for issue #341
withTestProcess("testvariables2", t, func(p *Process, fixture protest.Fixture) {
assertNoError(p.Continue(), t, "Continue()")
t.Logf("requesting mapinf")
mapinf, err := evalVariable(p, "mapinf")
assertNoError(err, t, "EvalVariable()")
t.Logf("mapinf: %v\n", mapinf)
for _, expr := range []string{"mapinf", "ptrinf", "sliceinf"} {
t.Logf("requesting %s", expr)
v, err := evalVariable(p, expr)
assertNoError(err, t, fmt.Sprintf("EvalVariable(%s)", expr))
t.Logf("%s: %v\n", expr, v)
}
})
}

@ -812,7 +812,12 @@ func (v *Variable) loadValueInternal(recurseLevel int, cfg LoadConfig) {
v.Children = []Variable{*v.maybeDereference()}
if cfg.FollowPointers {
// Don't increase the recursion level when dereferencing pointers
v.Children[0].loadValueInternal(recurseLevel, cfg)
// unless this is a pointer to interface (which could cause an infinite loop)
nextLvl := recurseLevel
if v.Children[0].Kind == reflect.Interface {
nextLvl++
}
v.Children[0].loadValueInternal(nextLvl, cfg)
} else {
v.Children[0].OnlyAddr = true
}
@ -1630,7 +1635,7 @@ func (v *Variable) loadInterface(recurseLevel int, loadData bool, cfg LoadConfig
data = data.newVariable("data", data.Addr, typ)
v.Children = []Variable{*data}
if loadData {
if loadData && recurseLevel <= cfg.MaxVariableRecurse {
v.Children[0].loadValueInternal(recurseLevel, cfg)
} else {
v.Children[0].OnlyAddr = true

@ -87,7 +87,9 @@ func (v *Variable) writeTo(buf io.Writer, top, newlines, includeType bool, inden
}
data := v.Children[0]
if data.Kind == reflect.Ptr {
if data.Children[0].Addr == 0 {
if len(data.Children) == 0 {
fmt.Fprintf(buf, "...")
} else if data.Children[0].Addr == 0 {
fmt.Fprintf(buf, "nil")
} else if data.Children[0].OnlyAddr {
fmt.Fprintf(buf, "0x%x", v.Children[0].Addr)