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:
parent
ce01a67d8b
commit
fc0d40144a
@ -212,6 +212,14 @@ func main() {
|
|||||||
ninf := math.Inf(-1)
|
ninf := math.Inf(-1)
|
||||||
nan := math.NaN()
|
nan := math.NaN()
|
||||||
|
|
||||||
|
var iface6 interface{}
|
||||||
|
var ptrinf *interface{}
|
||||||
|
iface6 = &ptrinf
|
||||||
|
ptrinf = &iface6
|
||||||
|
|
||||||
|
sliceinf := make([]interface{}, 1)
|
||||||
|
sliceinf[0] = sliceinf
|
||||||
|
|
||||||
var amb1 = 1
|
var amb1 = 1
|
||||||
runtime.Breakpoint()
|
runtime.Breakpoint()
|
||||||
for amb1 := 0; amb1 < 10; amb1++ {
|
for amb1 := 0; amb1 < 10; amb1++ {
|
||||||
|
@ -1440,14 +1440,17 @@ func TestIssue305(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIssue341(t *testing.T) {
|
func TestPointerLoops(t *testing.T) {
|
||||||
// pointer loop through map entries
|
// Pointer loops through map entries, pointers and slices
|
||||||
|
// Regression test for issue #341
|
||||||
withTestProcess("testvariables2", t, func(p *Process, fixture protest.Fixture) {
|
withTestProcess("testvariables2", t, func(p *Process, fixture protest.Fixture) {
|
||||||
assertNoError(p.Continue(), t, "Continue()")
|
assertNoError(p.Continue(), t, "Continue()")
|
||||||
t.Logf("requesting mapinf")
|
for _, expr := range []string{"mapinf", "ptrinf", "sliceinf"} {
|
||||||
mapinf, err := evalVariable(p, "mapinf")
|
t.Logf("requesting %s", expr)
|
||||||
assertNoError(err, t, "EvalVariable()")
|
v, err := evalVariable(p, expr)
|
||||||
t.Logf("mapinf: %v\n", mapinf)
|
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()}
|
v.Children = []Variable{*v.maybeDereference()}
|
||||||
if cfg.FollowPointers {
|
if cfg.FollowPointers {
|
||||||
// Don't increase the recursion level when dereferencing pointers
|
// 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 {
|
} else {
|
||||||
v.Children[0].OnlyAddr = true
|
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)
|
data = data.newVariable("data", data.Addr, typ)
|
||||||
|
|
||||||
v.Children = []Variable{*data}
|
v.Children = []Variable{*data}
|
||||||
if loadData {
|
if loadData && recurseLevel <= cfg.MaxVariableRecurse {
|
||||||
v.Children[0].loadValueInternal(recurseLevel, cfg)
|
v.Children[0].loadValueInternal(recurseLevel, cfg)
|
||||||
} else {
|
} else {
|
||||||
v.Children[0].OnlyAddr = true
|
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]
|
data := v.Children[0]
|
||||||
if data.Kind == reflect.Ptr {
|
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")
|
fmt.Fprintf(buf, "nil")
|
||||||
} else if data.Children[0].OnlyAddr {
|
} else if data.Children[0].OnlyAddr {
|
||||||
fmt.Fprintf(buf, "0x%x", v.Children[0].Addr)
|
fmt.Fprintf(buf, "0x%x", v.Children[0].Addr)
|
||||||
|
Loading…
Reference in New Issue
Block a user