From 8de1a307ee09500eb639b66c733d648254ccef12 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Fri, 7 Aug 2015 13:23:18 +0200 Subject: [PATCH] Fix: track recurseLevel in readArray/readSlice This fix helps avoid infinite recursion. --- _fixtures/testvariables2.go | 13 +++++++++++++ proc/variables.go | 16 ++++++++-------- proc/variables_test.go | 9 +++++++++ 3 files changed, 30 insertions(+), 8 deletions(-) create mode 100644 _fixtures/testvariables2.go diff --git a/_fixtures/testvariables2.go b/_fixtures/testvariables2.go new file mode 100644 index 00000000..b3816d47 --- /dev/null +++ b/_fixtures/testvariables2.go @@ -0,0 +1,13 @@ +package main + +import "runtime" + +type a struct { + aas []a +} + +func main() { + var aas = []a{{nil}} + aas[0].aas = aas + runtime.Breakpoint() +} diff --git a/proc/variables.go b/proc/variables.go index 9045ec53..4cf87ab3 100644 --- a/proc/variables.go +++ b/proc/variables.go @@ -522,7 +522,7 @@ func (thread *Thread) extractValueInternal(instructions []byte, addr int64, typ case t.StructName == "string": return thread.readString(ptraddress) case strings.HasPrefix(t.StructName, "[]"): - return thread.readSlice(ptraddress, t) + return thread.readSlice(ptraddress, t, recurseLevel) default: // Recursively call extractValue to grab // the value of all the members of the struct. @@ -548,7 +548,7 @@ func (thread *Thread) extractValueInternal(instructions []byte, addr int64, typ return "{...}", nil } case *dwarf.ArrayType: - return thread.readArray(ptraddress, t) + return thread.readArray(ptraddress, t, recurseLevel) case *dwarf.ComplexType: return thread.readComplex(ptraddress, t.ByteSize) case *dwarf.IntType: @@ -601,7 +601,7 @@ func (thread *Thread) readString(addr uintptr) (string, error) { return *(*string)(unsafe.Pointer(&val)), nil } -func (thread *Thread) readSlice(addr uintptr, t *dwarf.StructType) (string, error) { +func (thread *Thread) readSlice(addr uintptr, t *dwarf.StructType, recurseLevel int) (string, error) { var sliceLen, sliceCap int64 var arrayAddr uintptr var arrayType dwarf.Type @@ -644,7 +644,7 @@ func (thread *Thread) readSlice(addr uintptr, t *dwarf.StructType) (string, erro if _, ok := arrayType.(*dwarf.PtrType); ok { stride = int64(thread.dbp.arch.PtrSize()) } - vals, err := thread.readArrayValues(arrayAddr, sliceLen, stride, arrayType) + vals, err := thread.readArrayValues(arrayAddr, sliceLen, stride, arrayType, recurseLevel) if err != nil { return "", err } @@ -652,9 +652,9 @@ func (thread *Thread) readSlice(addr uintptr, t *dwarf.StructType) (string, erro return fmt.Sprintf("[]%s len: %d, cap: %d, [%s]", arrayType, sliceLen, sliceCap, strings.Join(vals, ",")), nil } -func (thread *Thread) readArray(addr uintptr, t *dwarf.ArrayType) (string, error) { +func (thread *Thread) readArray(addr uintptr, t *dwarf.ArrayType, recurseLevel int) (string, error) { if t.Count > 0 { - vals, err := thread.readArrayValues(addr, t.Count, t.ByteSize/t.Count, t.Type) + vals, err := thread.readArrayValues(addr, t.Count, t.ByteSize/t.Count, t.Type, recurseLevel) if err != nil { return "", err } @@ -664,7 +664,7 @@ func (thread *Thread) readArray(addr uintptr, t *dwarf.ArrayType) (string, error return fmt.Sprintf("%s []", t), nil } -func (thread *Thread) readArrayValues(addr uintptr, count int64, stride int64, t dwarf.Type) ([]string, error) { +func (thread *Thread) readArrayValues(addr uintptr, count int64, stride int64, t dwarf.Type, recurseLevel int) ([]string, error) { vals := make([]string, 0) for i := int64(0); i < count; i++ { @@ -674,7 +674,7 @@ func (thread *Thread) readArrayValues(addr uintptr, count int64, stride int64, t break } - val, err := thread.extractValue(nil, int64(addr+uintptr(i*stride)), t, false) + val, err := thread.extractValueInternal(nil, int64(addr+uintptr(i*stride)), t, false, recurseLevel+1) if err != nil { return nil, err } diff --git a/proc/variables_test.go b/proc/variables_test.go index ba82de93..f5785330 100644 --- a/proc/variables_test.go +++ b/proc/variables_test.go @@ -216,3 +216,12 @@ func TestLocalVariables(t *testing.T) { } }) } + +func TestRecursiveStructure(t *testing.T) { + withTestProcess("testvariables2", t, func(p *Process, fixture protest.Fixture) { + assertNoError(p.Continue(), t, "Continue()") + v, err := p.EvalVariable("aas") + assertNoError(err, t, "EvalVariable()") + t.Logf("v: %v\n", v) + }) +}