mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
Ironically, checkptrAlignment had a latent case of bad pointer arithmetic: if ptr is nil, then `add(ptr, size-1)` might produce an illegal pointer value. The fix is to simply check for nil at the top of checkptrAlignment, and short-circuit if so. This CL also adds a more explicit bounds check in checkptrStraddles, rather than relying on `add(ptr, size-1)` to wrap around. I don't think this is necessary today, but it seems prudent to be careful. Fixes #47430. Change-Id: I5c50b2f7f41415dbebbd803e1b8e7766ca95e1fd Reviewed-on: https://go-review.googlesource.com/c/go/+/338029 Trust: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
98 lines
1.9 KiB
Go
98 lines
1.9 KiB
Go
// Copyright 2020 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package main
|
|
|
|
import (
|
|
"runtime"
|
|
"time"
|
|
"unsafe"
|
|
)
|
|
|
|
func init() {
|
|
register("CheckPtrAlignmentNoPtr", CheckPtrAlignmentNoPtr)
|
|
register("CheckPtrAlignmentPtr", CheckPtrAlignmentPtr)
|
|
register("CheckPtrAlignmentNilPtr", CheckPtrAlignmentNilPtr)
|
|
register("CheckPtrArithmetic", CheckPtrArithmetic)
|
|
register("CheckPtrArithmetic2", CheckPtrArithmetic2)
|
|
register("CheckPtrSize", CheckPtrSize)
|
|
register("CheckPtrSmall", CheckPtrSmall)
|
|
register("CheckPtrSliceOK", CheckPtrSliceOK)
|
|
register("CheckPtrSliceFail", CheckPtrSliceFail)
|
|
}
|
|
|
|
func CheckPtrAlignmentNoPtr() {
|
|
var x [2]int64
|
|
p := unsafe.Pointer(&x[0])
|
|
sink2 = (*int64)(unsafe.Pointer(uintptr(p) + 1))
|
|
}
|
|
|
|
func CheckPtrAlignmentPtr() {
|
|
var x [2]int64
|
|
p := unsafe.Pointer(&x[0])
|
|
sink2 = (**int64)(unsafe.Pointer(uintptr(p) + 1))
|
|
}
|
|
|
|
// CheckPtrAlignmentNilPtr tests that checkptrAlignment doesn't crash
|
|
// on nil pointers (#47430).
|
|
func CheckPtrAlignmentNilPtr() {
|
|
var do func(int)
|
|
do = func(n int) {
|
|
// Inflate the stack so runtime.shrinkstack gets called during GC
|
|
if n > 0 {
|
|
do(n - 1)
|
|
}
|
|
|
|
var p unsafe.Pointer
|
|
_ = (*int)(p)
|
|
}
|
|
|
|
go func() {
|
|
for {
|
|
runtime.GC()
|
|
}
|
|
}()
|
|
|
|
go func() {
|
|
for i := 0; ; i++ {
|
|
do(i % 1024)
|
|
}
|
|
}()
|
|
|
|
time.Sleep(time.Second)
|
|
}
|
|
|
|
func CheckPtrArithmetic() {
|
|
var x int
|
|
i := uintptr(unsafe.Pointer(&x))
|
|
sink2 = (*int)(unsafe.Pointer(i))
|
|
}
|
|
|
|
func CheckPtrArithmetic2() {
|
|
var x [2]int64
|
|
p := unsafe.Pointer(&x[1])
|
|
var one uintptr = 1
|
|
sink2 = unsafe.Pointer(uintptr(p) & ^one)
|
|
}
|
|
|
|
func CheckPtrSize() {
|
|
p := new(int64)
|
|
sink2 = p
|
|
sink2 = (*[100]int64)(unsafe.Pointer(p))
|
|
}
|
|
|
|
func CheckPtrSmall() {
|
|
sink2 = unsafe.Pointer(uintptr(1))
|
|
}
|
|
|
|
func CheckPtrSliceOK() {
|
|
p := new([4]int64)
|
|
sink2 = unsafe.Slice(&p[1], 3)
|
|
}
|
|
|
|
func CheckPtrSliceFail() {
|
|
p := new(int64)
|
|
sink2 = p
|
|
sink2 = unsafe.Slice(p, 100)
|
|
}
|