From: cuiweixie Date: Mon, 8 Aug 2022 16:07:05 +0000 (+0000) Subject: cmd/compile,runtime: panic when unsafe.Slice param is nil and > 0 X-Git-Tag: go1.20rc1~1773 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=52d0667e6ba69059422a138dd6589f3f697fc0db;p=gostls13.git cmd/compile,runtime: panic when unsafe.Slice param is nil and > 0 Fixes #54092 Change-Id: Ib917922ed36ee5410e5515f812737203c44f46ae GitHub-Last-Rev: dfd0c3883cf8b10479d9c5b389baa1a04c52dd34 GitHub-Pull-Request: golang/go#54107 Reviewed-on: https://go-review.googlesource.com/c/go/+/419755 Run-TryBot: Cuong Manh Le Reviewed-by: Cuong Manh Le Reviewed-by: Than McIntosh Reviewed-by: Keith Randall Reviewed-by: Keith Randall TryBot-Result: Gopher Robot --- diff --git a/src/cmd/compile/internal/walk/builtin.go b/src/cmd/compile/internal/walk/builtin.go index 7e84f28217..5a649c0951 100644 --- a/src/cmd/compile/internal/walk/builtin.go +++ b/src/cmd/compile/internal/walk/builtin.go @@ -682,6 +682,25 @@ func walkUnsafeSlice(n *ir.BinaryExpr, init *ir.Nodes) ir.Node { nif.Body.Append(mkcall("panicunsafeslicelen", nil, &nif.Body)) appendWalkStmt(init, nif) + if sliceType.Elem().Size() == 0 { + // if ptr == nil && len > 0 { + // panicunsafesliceptrnil() + // } + nifPtr := ir.NewIfStmt(base.Pos, nil, nil, nil) + isNil := ir.NewBinaryExpr(base.Pos, ir.OEQ, unsafePtr, typecheck.NodNil()) + gtZero := ir.NewBinaryExpr(base.Pos, ir.OGT, typecheck.Conv(len, lenType), ir.NewInt(0)) + nifPtr.Cond = + ir.NewLogicalExpr(base.Pos, ir.OANDAND, isNil, gtZero) + nifPtr.Body.Append(mkcall("panicunsafeslicenilptr", nil, &nifPtr.Body)) + appendWalkStmt(init, nifPtr) + + h := ir.NewSliceHeaderExpr(n.Pos(), sliceType, + typecheck.Conv(ptr, types.Types[types.TUNSAFEPTR]), + typecheck.Conv(len, types.Types[types.TINT]), + typecheck.Conv(len, types.Types[types.TINT])) + return walkExpr(typecheck.Expr(h), init) + } + // mem, overflow := runtime.mulUintptr(et.size, len) mem := typecheck.Temp(types.Types[types.TUINTPTR]) overflow := typecheck.Temp(types.Types[types.TBOOL]) diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go index 01d7cbeb29..02604595ac 100644 --- a/src/runtime/crash_test.go +++ b/src/runtime/crash_test.go @@ -844,3 +844,11 @@ func TestPanicWhilePanicking(t *testing.T) { } } } + +func TestPanicOnUnsafeSlice(t *testing.T) { + output := runTestProg(t, "testprog", "panicOnNilAndEleSizeIsZero") + want := "panic: runtime error: unsafe.Slice: ptr is nil and len is not zero" + if !strings.Contains(output, want) { + t.Errorf("output does not contain %q:\n%s", want, output) + } +} \ No newline at end of file diff --git a/src/runtime/slice.go b/src/runtime/slice.go index 2413a46d6a..8a0ce49fad 100644 --- a/src/runtime/slice.go +++ b/src/runtime/slice.go @@ -129,6 +129,12 @@ func unsafeslice(et *_type, ptr unsafe.Pointer, len int) { panicunsafeslicelen() } + if et.size == 0 { + if ptr == nil && len > 0 { + panicunsafeslicenilptr() + } + } + mem, overflow := math.MulUintptr(et.size, uintptr(len)) if overflow || mem > -uintptr(ptr) { if ptr == nil { diff --git a/src/runtime/testdata/testprog/unsafe.go b/src/runtime/testdata/testprog/unsafe.go new file mode 100644 index 0000000000..d6dddf22c2 --- /dev/null +++ b/src/runtime/testdata/testprog/unsafe.go @@ -0,0 +1,12 @@ +package main + +import "unsafe" + +func init() { + register("panicOnNilAndEleSizeIsZero", panicOnNilAndEleSizeIsZero) +} + +func panicOnNilAndEleSizeIsZero() { + var p *struct{} + _ = unsafe.Slice(p, 5) +} \ No newline at end of file