From 8e99c3313bee8d3dd15ccf476321070d7da8ee81 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Thu, 10 Jan 2019 14:09:04 +0100 Subject: [PATCH] compiler: fix make([]T, ...) with big integers on 32-bit systems or less Previously, this would have resulted in a LLVM verification error because runtime.sliceBoundsCheckMake would not accept 64-bit integers on these platforms. --- compiler/compiler.go | 24 +++++++++++++++++------- src/runtime/panic.go | 7 +++++++ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/compiler/compiler.go b/compiler/compiler.go index cf5a61c6..625dcc77 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -1730,21 +1730,31 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) { // Bounds checking. if !frame.fn.IsNoBounds() { - if sliceLen.Type().IntTypeWidth() < c.uintptrType.IntTypeWidth() { + checkFunc := "sliceBoundsCheckMake" + biggestInt := c.uintptrType + biggestIntWidth := biggestInt.IntTypeWidth() + if sliceLen.Type().IntTypeWidth() > biggestIntWidth || sliceCap.Type().IntTypeWidth() > biggestIntWidth { + // System that is less than 64bit, meaning that the slice make + // params are bigger than uintptr. + checkFunc = "sliceBoundsCheckMake64" + biggestInt = c.ctx.Int64Type() + biggestIntWidth = biggestInt.IntTypeWidth() + } + if sliceLen.Type().IntTypeWidth() < biggestIntWidth { if expr.Len.Type().(*types.Basic).Info()&types.IsUnsigned != 0 { - sliceLen = c.builder.CreateZExt(sliceLen, c.uintptrType, "") + sliceLen = c.builder.CreateZExt(sliceLen, biggestInt, "") } else { - sliceLen = c.builder.CreateSExt(sliceLen, c.uintptrType, "") + sliceLen = c.builder.CreateSExt(sliceLen, biggestInt, "") } } - if sliceCap.Type().IntTypeWidth() < c.uintptrType.IntTypeWidth() { + if sliceCap.Type().IntTypeWidth() < biggestIntWidth { if expr.Cap.Type().(*types.Basic).Info()&types.IsUnsigned != 0 { - sliceCap = c.builder.CreateZExt(sliceCap, c.uintptrType, "") + sliceCap = c.builder.CreateZExt(sliceCap, biggestInt, "") } else { - sliceCap = c.builder.CreateSExt(sliceCap, c.uintptrType, "") + sliceCap = c.builder.CreateSExt(sliceCap, biggestInt, "") } } - c.createRuntimeCall("sliceBoundsCheckMake", []llvm.Value{sliceLen, sliceCap}, "") + c.createRuntimeCall(checkFunc, []llvm.Value{sliceLen, sliceCap}, "") } // Allocate the backing array. diff --git a/src/runtime/panic.go b/src/runtime/panic.go index e00ec2fe..9140fcd0 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -62,3 +62,10 @@ func sliceBoundsCheckMake(length, capacity uint) { runtimePanic("slice size out of range") } } + +// Check for bounds in *ssa.MakeSlice. Supports 64-bit indexes. +func sliceBoundsCheckMake64(length, capacity uint64) { + if !(0 <= length && length <= capacity) { + runtimePanic("slice size out of range") + } +}