go/ssa/interp: handle nil slice convert to array pointer

Converting from nil slice to a zero length array pointer must be nil.

Updates golang/go#46987

Change-Id: I8894b92bd85fae8ea77bf01b92ee56f1a215a75b
Reviewed-on: https://go-review.googlesource.com/c/tools/+/336489
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Trust: Tim King <taking@google.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Tim King <taking@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Tim King <taking@google.com>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
This commit is contained in:
Cuong Manh Le 2021-07-22 10:42:02 +07:00
parent ab1fe7202b
commit 3810fa8296
2 changed files with 45 additions and 18 deletions

View File

@ -1367,11 +1367,13 @@ func sliceToArrayPointer(t_dst, t_src types.Type, x value) value {
if utSrc, ok := utDst.(*types.Pointer); ok {
if arr, ok := utSrc.Elem().(*types.Array); ok {
x := x.([]value)
a := make(array, arr.Len())
for i := range a {
a[i] = x[i]
if arr.Len() > int64(len(x)) {
panic("array length is greater than slice length")
}
v := value(a)
if x == nil {
return zero(utSrc)
}
v := value(array(x[:arr.Len()]))
return &v
}
}

View File

@ -2,22 +2,47 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test for slice to array pointer conversion introduced in go1.17
// See: https://tip.golang.org/ref/spec#Conversions_from_slice_to_array_pointer
package main
// Test for slice to array pointer conversion introduced in go1.17
import "fmt"
var s = []byte{1, 2, 3, 4}
var a = (*[4]byte)(s)
func main() {
for i := range s {
if a[i] != s[i] {
panic(fmt.Sprintf("value mismatched: %v - %v\n", a[i], s[i]))
}
if (*a)[i] != s[i] {
panic(fmt.Sprintf("value mismatched: %v - %v\n", (*a)[i], s[i]))
}
s := make([]byte, 2, 4)
if s0 := (*[0]byte)(s); s0 == nil {
panic("converted from non-nil slice result in nil array pointer")
}
if s2 := (*[2]byte)(s); &s2[0] != &s[0] {
panic("the converted array is not slice underlying array")
}
wantPanic(
func() {
_ = (*[4]byte)(s) // panics: len([4]byte) > len(s)
},
"runtime error: array length is greater than slice length",
)
var t []string
if t0 := (*[0]string)(t); t0 != nil {
panic("nil slice converted to *[0]byte should be nil")
}
wantPanic(
func() {
_ = (*[1]string)(t) // panics: len([1]string) > len(t)
},
"runtime error: array length is greater than slice length",
)
}
func wantPanic(fn func(), s string) {
defer func() {
err := recover()
if err == nil {
panic("expected panic")
}
if got := err.(error).Error(); got != s {
panic("expected panic " + s + " got " + got)
}
}()
fn()
}