diff options
Diffstat (limited to 'src/reflect/value.go')
-rw-r--r-- | src/reflect/value.go | 26 |
1 files changed, 16 insertions, 10 deletions
diff --git a/src/reflect/value.go b/src/reflect/value.go index 1abfbe6f65..125f04eaee 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -630,8 +630,11 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer) { args := framePool.Get().(unsafe.Pointer) // Copy in receiver and rest of args. + // Avoid constructing out-of-bounds pointers if there are no args. storeRcvr(rcvr, args) - typedmemmovepartial(frametype, unsafe.Pointer(uintptr(args)+ptrSize), frame, ptrSize, argSize-ptrSize) + if argSize-ptrSize > 0 { + typedmemmovepartial(frametype, unsafe.Pointer(uintptr(args)+ptrSize), frame, ptrSize, argSize-ptrSize) + } // Call. call(frametype, fn, args, uint32(frametype.size), uint32(retOffset)) @@ -641,15 +644,18 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer) { // a receiver) is different from the layout of the fn call, which has // a receiver. // Ignore any changes to args and just copy return values. - callerRetOffset := retOffset - ptrSize - if runtime.GOARCH == "amd64p32" { - callerRetOffset = align(argSize-ptrSize, 8) - } - typedmemmovepartial(frametype, - unsafe.Pointer(uintptr(frame)+callerRetOffset), - unsafe.Pointer(uintptr(args)+retOffset), - retOffset, - frametype.size-retOffset) + // Avoid constructing out-of-bounds pointers if there are no return values. + if frametype.size-retOffset > 0 { + callerRetOffset := retOffset - ptrSize + if runtime.GOARCH == "amd64p32" { + callerRetOffset = align(argSize-ptrSize, 8) + } + typedmemmovepartial(frametype, + unsafe.Pointer(uintptr(frame)+callerRetOffset), + unsafe.Pointer(uintptr(args)+retOffset), + retOffset, + frametype.size-retOffset) + } // This is untyped because the frame is really a stack, even // though it's a heap object. |