diff options
author | Cherry Mui <cherryyz@google.com> | 2021-07-14 18:52:44 -0400 |
---|---|---|
committer | Cherry Mui <cherryyz@google.com> | 2021-07-19 18:00:46 +0000 |
commit | 404127c30f3f66eb234da2dc1a78e6eea0ef4ee0 (patch) | |
tree | fb846d3500b168872b95530986bb8a6a5811f109 /src/cmd/compile/internal/ssagen | |
parent | 6298cfe6724e3ca24dedd3f62b2b358aafe17276 (diff) | |
download | go-404127c30f3f66eb234da2dc1a78e6eea0ef4ee0.tar.gz go-404127c30f3f66eb234da2dc1a78e6eea0ef4ee0.zip |
cmd/compile: fix off-by-one error in traceback argument counting
For traceback argument printing, we want to print at most 10
words, then print "..." if there are still more args and/or
fields. The current code has off-by-one error that for 11
non-aggregate typed args, it prints the first 10 but without the
"...". Also, for aggregate-typed args, in some cases it may print
an extra "..." when there is actually no more fields.
The problem for this is that visitType return false (meaning not
to continue visiting) if it reaches the limit anywhere during the
recursive visit. It doesn't distinguish whether it has printed
anything for the current arg. If it reaches the limit before it
prints anything, it means that we're visiting the extra arg/field,
so the caller should print "..." and stop. If it prints
something then reaches the limit, however, the caller should keep
going, and only print "..." at the next iteration when there is
actually an extra arg/field. This CL does so.
Fixes #47159.
Change-Id: I93fc25b73ada2b5a98df780c45e5b0c9565dc2fc
Reviewed-on: https://go-review.googlesource.com/c/go/+/334710
Trust: Cherry Mui <cherryyz@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Diffstat (limited to 'src/cmd/compile/internal/ssagen')
-rw-r--r-- | src/cmd/compile/internal/ssagen/ssa.go | 43 |
1 files changed, 15 insertions, 28 deletions
diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index f1dc56e729..a5cb0857b3 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -6598,6 +6598,7 @@ func EmitArgInfo(f *ir.Func, abiInfo *abi.ABIParamResultInfo) *obj.LSym { x := base.Ctxt.Lookup(fmt.Sprintf("%s.arginfo%d", f.LSym.Name, f.ABI)) PtrSize := int64(types.PtrSize) + uintptrTyp := types.Types[types.TUINTPTR] isAggregate := func(t *types.Type) bool { return t.IsStruct() || t.IsArray() || t.IsComplex() || t.IsInterface() || t.IsString() || t.IsSlice() @@ -6641,12 +6642,8 @@ func EmitArgInfo(f *ir.Func, abiInfo *abi.ABIParamResultInfo) *obj.LSym { n := 0 writebyte := func(o uint8) { wOff = objw.Uint8(x, wOff, o) } - // Write one non-aggrgate arg/field/element if there is room. - // Returns whether to continue. - write1 := func(sz, offset int64) bool { - if n >= limit { - return false - } + // Write one non-aggrgate arg/field/element. + write1 := func(sz, offset int64) { if offset >= _special { writebyte(_offsetTooLarge) } else { @@ -6654,7 +6651,6 @@ func EmitArgInfo(f *ir.Func, abiInfo *abi.ABIParamResultInfo) *obj.LSym { writebyte(uint8(sz)) } n++ - return true } // Visit t recursively and write it out. @@ -6662,10 +6658,12 @@ func EmitArgInfo(f *ir.Func, abiInfo *abi.ABIParamResultInfo) *obj.LSym { var visitType func(baseOffset int64, t *types.Type, depth int) bool visitType = func(baseOffset int64, t *types.Type, depth int) bool { if n >= limit { + writebyte(_dotdotdot) return false } if !isAggregate(t) { - return write1(t.Size(), baseOffset) + write1(t.Size(), baseOffset) + return true } writebyte(_startAgg) depth++ @@ -6675,58 +6673,47 @@ func EmitArgInfo(f *ir.Func, abiInfo *abi.ABIParamResultInfo) *obj.LSym { n++ return true } - var r bool switch { case t.IsInterface(), t.IsString(): - r = write1(PtrSize, baseOffset) && - write1(PtrSize, baseOffset+PtrSize) + _ = visitType(baseOffset, uintptrTyp, depth) && + visitType(baseOffset+PtrSize, uintptrTyp, depth) case t.IsSlice(): - r = write1(PtrSize, baseOffset) && - write1(PtrSize, baseOffset+PtrSize) && - write1(PtrSize, baseOffset+PtrSize*2) + _ = visitType(baseOffset, uintptrTyp, depth) && + visitType(baseOffset+PtrSize, uintptrTyp, depth) && + visitType(baseOffset+PtrSize*2, uintptrTyp, depth) case t.IsComplex(): - r = write1(t.Size()/2, baseOffset) && - write1(t.Size()/2, baseOffset+t.Size()/2) + _ = visitType(baseOffset, types.FloatForComplex(t), depth) && + visitType(baseOffset+t.Size()/2, types.FloatForComplex(t), depth) case t.IsArray(): - r = true if t.NumElem() == 0 { n++ // {} counts as a component break } for i := int64(0); i < t.NumElem(); i++ { if !visitType(baseOffset, t.Elem(), depth) { - r = false break } baseOffset += t.Elem().Size() } case t.IsStruct(): - r = true if t.NumFields() == 0 { n++ // {} counts as a component break } for _, field := range t.Fields().Slice() { if !visitType(baseOffset+field.Offset, field.Type, depth) { - r = false break } } } - if !r { - writebyte(_dotdotdot) - } writebyte(_endAgg) - return r + return true } - c := true for _, a := range abiInfo.InParams() { - if !c { - writebyte(_dotdotdot) + if !visitType(a.FrameOffset(abiInfo), a.Type, 0) { break } - c = visitType(a.FrameOffset(abiInfo), a.Type, 0) } writebyte(_endSeq) if wOff > maxLen { |