Skip to content

Commit

Permalink
cmd/compile,runtime: panic when unsafe.Slice param is nil and sizeof(…
Browse files Browse the repository at this point in the history
…elem) == 0 and > 0

Fixes golang#54092
  • Loading branch information
cuiweixie committed Aug 8, 2022
1 parent 487b350 commit dfd0c38
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/cmd/compile/internal/walk/builtin.go
Expand Up @@ -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])
Expand Down
8 changes: 8 additions & 0 deletions src/runtime/crash_test.go
Expand Up @@ -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)
}
}
6 changes: 6 additions & 0 deletions src/runtime/slice.go
Expand Up @@ -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 {
Expand Down
12 changes: 12 additions & 0 deletions 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)
}

0 comments on commit dfd0c38

Please sign in to comment.