]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile, runtime: add checkptr instrumentation for unsafe.Add
authorCuong Manh Le <cuong.manhle.vn@gmail.com>
Tue, 29 Jul 2025 11:45:23 +0000 (18:45 +0700)
committerGopher Robot <gobot@golang.org>
Tue, 5 Aug 2025 15:28:50 +0000 (08:28 -0700)
Fixes #74431

Change-Id: Id651ea0b82599ccaff8816af0a56ddbb149b6f89
Reviewed-on: https://go-review.googlesource.com/c/go/+/692015
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@golang.org>
Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: t hepudds <thepudds1460@gmail.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
src/cmd/compile/internal/walk/expr.go
src/runtime/checkptr_test.go
src/runtime/testdata/testprog/checkptr.go

index fbfc56a39c307139b907596f81e047fb13d9e189..b9e226b20741fcc3d09d75aebb721bda5232007f 100644 (file)
@@ -131,6 +131,14 @@ func walkExpr1(n ir.Node, init *ir.Nodes) ir.Node {
                n := n.(*ir.BinaryExpr)
                n.X = walkExpr(n.X, init)
                n.Y = walkExpr(n.Y, init)
+               if n.Op() == ir.OUNSAFEADD && ir.ShouldCheckPtr(ir.CurFunc, 1) {
+                       // For unsafe.Add(p, n), just walk "unsafe.Pointer(uintptr(p)+uintptr(n))"
+                       // for the side effects of validating unsafe.Pointer rules.
+                       x := typecheck.ConvNop(n.X, types.Types[types.TUINTPTR])
+                       y := typecheck.Conv(n.Y, types.Types[types.TUINTPTR])
+                       conv := typecheck.ConvNop(ir.NewBinaryExpr(n.Pos(), ir.OADD, x, y), types.Types[types.TUNSAFEPTR])
+                       walkExpr(conv, init)
+               }
                return n
 
        case ir.OUNSAFESLICE:
index 811c0f035534205684740b9569d0c26785315cd3..119708be7f52aca74b9d2c1841667ba760341c3c 100644 (file)
@@ -35,6 +35,7 @@ func TestCheckPtr(t *testing.T) {
                {"CheckPtrAlignmentNilPtr", ""},
                {"CheckPtrArithmetic", "fatal error: checkptr: pointer arithmetic result points to invalid allocation\n"},
                {"CheckPtrArithmetic2", "fatal error: checkptr: pointer arithmetic result points to invalid allocation\n"},
+               {"CheckPtrArithmeticUnsafeAdd", "fatal error: checkptr: pointer arithmetic result points to invalid allocation\n"},
                {"CheckPtrSize", "fatal error: checkptr: converted pointer straddles multiple allocations\n"},
                {"CheckPtrSmall", "fatal error: checkptr: pointer arithmetic computed bad pointer value\n"},
                {"CheckPtrSliceOK", ""},
index 60e71e66d7f4f5242624b589d7271091e3725169..ff99fa8c7b702f6e6c8b4e31fe3af42a7922a1c3 100644 (file)
@@ -16,6 +16,7 @@ func init() {
        register("CheckPtrAlignmentNilPtr", CheckPtrAlignmentNilPtr)
        register("CheckPtrArithmetic", CheckPtrArithmetic)
        register("CheckPtrArithmetic2", CheckPtrArithmetic2)
+       register("CheckPtrArithmeticUnsafeAdd", CheckPtrArithmeticUnsafeAdd)
        register("CheckPtrSize", CheckPtrSize)
        register("CheckPtrSmall", CheckPtrSmall)
        register("CheckPtrSliceOK", CheckPtrSliceOK)
@@ -79,6 +80,11 @@ func CheckPtrArithmetic2() {
        sink2 = unsafe.Pointer(uintptr(p) & ^one)
 }
 
+func CheckPtrArithmeticUnsafeAdd() {
+       data := make([]byte, 128)
+       sink2 = (*byte)(unsafe.Add(unsafe.Pointer(unsafe.SliceData(data)), len(data)))
+}
+
 func CheckPtrSize() {
        p := new(int64)
        sink2 = p