aboutsummaryrefslogtreecommitdiff
path: root/src/reflect/value.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/reflect/value.go')
-rw-r--r--src/reflect/value.go26
1 files changed, 16 insertions, 10 deletions
diff --git a/src/reflect/value.go b/src/reflect/value.go
index 699ba69408..387b9f3c13 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.