From 5ab9f23977694ab87614fd30e081d294eb313efd Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 29 Jul 2025 18:45:23 +0700 Subject: [PATCH] cmd/compile, runtime: add checkptr instrumentation for unsafe.Add Fixes #74431 Change-Id: Id651ea0b82599ccaff8816af0a56ddbb149b6f89 Reviewed-on: https://go-review.googlesource.com/c/go/+/692015 LUCI-TryBot-Result: Go LUCI Reviewed-by: Keith Randall Auto-Submit: Cuong Manh Le Reviewed-by: Keith Randall Reviewed-by: t hepudds Reviewed-by: Dmitri Shuralyov --- src/cmd/compile/internal/walk/expr.go | 8 ++++++++ src/runtime/checkptr_test.go | 1 + src/runtime/testdata/testprog/checkptr.go | 6 ++++++ 3 files changed, 15 insertions(+) diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index fbfc56a39c..b9e226b207 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -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: diff --git a/src/runtime/checkptr_test.go b/src/runtime/checkptr_test.go index 811c0f0355..119708be7f 100644 --- a/src/runtime/checkptr_test.go +++ b/src/runtime/checkptr_test.go @@ -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", ""}, diff --git a/src/runtime/testdata/testprog/checkptr.go b/src/runtime/testdata/testprog/checkptr.go index 60e71e66d7..ff99fa8c7b 100644 --- a/src/runtime/testdata/testprog/checkptr.go +++ b/src/runtime/testdata/testprog/checkptr.go @@ -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 -- 2.51.0