From c41bcba9ce53ba006d250fafd636f1cdab08b0e4 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sun, 24 May 2026 20:58:56 +0800 Subject: [PATCH] fix makeslice panic text for constant cap --- cl/compile.go | 51 +++++++++++++++++ test/go/makeslice_panic_test.go | 99 +++++++++++++++++++++++++++++++++ test/goroot/xfail.yaml | 19 ------- 3 files changed, 150 insertions(+), 19 deletions(-) create mode 100644 test/go/makeslice_panic_test.go diff --git a/cl/compile.go b/cl/compile.go index 5b6d7c9fbe..68ace59c35 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -772,6 +772,50 @@ func (p *context) checkVArgs(v *ssa.Alloc, t *types.Pointer) bool { return false } +func (p *context) skipSyntheticMakeSliceAlloc(v *ssa.Alloc) bool { + refs := v.Referrers() + if refs == nil || len(*refs) != 1 { + return false + } + slice, ok := (*refs)[0].(*ssa.Slice) + if !ok { + return false + } + _, ok = p.syntheticMakeSliceCap(slice) + return ok +} + +func (p *context) compileSyntheticMakeSlice(b llssa.Builder, v *ssa.Slice) (llssa.Expr, bool) { + capacity, ok := p.syntheticMakeSliceCap(v) + if !ok { + return llssa.Expr{}, false + } + t := p.type_(v.Type(), llssa.InGo) + length := p.compileValue(b, v.High) + return b.MakeSlice(t, length, capacity), true +} + +func (p *context) syntheticMakeSliceCap(v *ssa.Slice) (llssa.Expr, bool) { + alloc, ok := v.X.(*ssa.Alloc) + if !ok || alloc.Comment != "makeslice" || v.Low != nil || v.High == nil || v.Max != nil { + return llssa.Expr{}, false + } + t, ok := alloc.Type().(*types.Pointer) + if !ok { + return llssa.Expr{}, false + } + arr, ok := t.Elem().(*types.Array) + if !ok { + return llssa.Expr{}, false + } + if high, ok := v.High.(*ssa.Const); ok { + if n, exact := constant.Int64Val(high.Value); exact && n >= 0 && n <= arr.Len() { + return llssa.Expr{}, false + } + } + return p.prog.IntVal(uint64(arr.Len()), p.prog.Int()), true +} + func isAllocVargs(ctx *context, v *ssa.Alloc) bool { refs := *v.Referrers() n := len(refs) @@ -924,6 +968,9 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue if p.checkVArgs(v, t) { // varargs: this maybe a varargs allocation return } + if p.skipSyntheticMakeSliceAlloc(v) { + return + } elem := p.type_(t.Elem(), llssa.InGo) ret = b.Alloc(elem, v.Heap) case *ssa.IndexAddr: @@ -951,6 +998,10 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue idx := p.compileValue(b, v.Index) ret = b.Lookup(x, idx, v.CommaOk) case *ssa.Slice: + if makeSlice, ok := p.compileSyntheticMakeSlice(b, v); ok { + ret = makeSlice + break + } vx := v.X if _, ok := p.isVArgs(vx); ok { // varargs: this is a varargs slice return diff --git a/test/go/makeslice_panic_test.go b/test/go/makeslice_panic_test.go new file mode 100644 index 0000000000..1fdaca4bb9 --- /dev/null +++ b/test/go/makeslice_panic_test.go @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2026 The XGo Authors (xgo.dev). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package gotest + +import ( + "fmt" + "testing" +) + +func TestMakeSlicePanicText(t *testing.T) { + tests := []struct { + name string + want string + f func() + }{ + { + name: "cap out of range from propagated local", + want: "runtime error: makeslice: cap out of range", + f: func() { + i := 2 + s := make([]int, i, 1) + s[0] = 1 + }, + }, + { + name: "cap out of range from parameter", + want: "runtime error: makeslice: cap out of range", + f: func() { + makeSliceCapPanic(2) + }, + }, + { + name: "len out of range from propagated local", + want: "runtime error: makeslice: len out of range", + f: func() { + i := -1 + s := make([]int, i, 3) + s[0] = 1 + }, + }, + { + name: "len out of range from parameter", + want: "runtime error: makeslice: len out of range", + f: func() { + makeSliceLenPanic(-1) + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + expectMakeSlicePanic(t, tt.want, tt.f) + }) + } +} + +func makeSliceCapPanic(i int) { + s := make([]int, i, 1) + s[0] = 1 +} + +func makeSliceLenPanic(i int) { + s := make([]int, i, 3) + s[0] = 1 +} + +func expectMakeSlicePanic(t *testing.T, want string, f func()) { + t.Helper() + defer func() { + err := recover() + if err == nil { + t.Fatalf("expected panic %q", want) + } + if got := makeSlicePanicString(err); got != want { + t.Fatalf("panic = %q, want %q", got, want) + } + }() + f() +} + +func makeSlicePanicString(v any) string { + if err, ok := v.(interface{ Error() string }); ok { + return err.Error() + } + return fmt.Sprint(v) +} diff --git a/test/goroot/xfail.yaml b/test/goroot/xfail.yaml index a5a66d10b4..2b827a1a73 100644 --- a/test/goroot/xfail.yaml +++ b/test/goroot/xfail.yaml @@ -1842,10 +1842,6 @@ xfails: directive: run case: fixedbugs/issue22881.go reason: current main goroot run failure on darwin/arm64 - - platform: darwin/arm64 - directive: run - case: fixedbugs/issue37975.go - reason: current main goroot run failure on darwin/arm64 - platform: darwin/arm64 directive: run case: fixedbugs/issue63657.go @@ -1977,11 +1973,6 @@ xfails: directive: run case: fixedbugs/issue22881.go reason: go1.24 goroot run failure on linux/amd64 - - version: go1.24 - platform: linux/amd64 - directive: run - case: fixedbugs/issue37975.go - reason: go1.24 goroot run failure on linux/amd64 - version: go1.24 platform: linux/amd64 directive: run @@ -2087,11 +2078,6 @@ xfails: directive: run case: fixedbugs/issue22881.go reason: go1.25 goroot run failure on linux/amd64 - - version: go1.25 - platform: linux/amd64 - directive: run - case: fixedbugs/issue37975.go - reason: go1.25 goroot run failure on linux/amd64 - version: go1.25 platform: linux/amd64 directive: run @@ -2202,11 +2188,6 @@ xfails: directive: run case: fixedbugs/issue22881.go reason: go1.26 goroot run failure on linux/amd64 - - version: go1.26 - platform: linux/amd64 - directive: run - case: fixedbugs/issue37975.go - reason: go1.26 goroot run failure on linux/amd64 - version: go1.26 platform: linux/amd64 directive: run