]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.26] cmd/compile: avoid folding 64-bit integers into 32-bit constants
authorYoulin Feng <fengyoulin@live.com>
Sat, 14 Feb 2026 10:55:34 +0000 (18:55 +0800)
committerDavid Chase <drchase@google.com>
Wed, 25 Feb 2026 19:17:53 +0000 (11:17 -0800)
Folding a 64-bit integer into a 32-bit constant may result in a negative
integer if the value exceeds math.MaxInt32 (the maximum value of a 32-
bit signed integer). This negative value will be sign-extended to 64
bits at runtime, leading to unexpected results when used in bitwise
AND/OR operations.

Fixes #77618

Change-Id: Idb081a3c20c28bddddcc8eff1225d62123b37a2d
Reviewed-on: https://go-review.googlesource.com/c/go/+/745581
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
(cherry picked from commit 3c8b5e673816c733f13a38b1ed1f53d7d49ea084)
Reviewed-on: https://go-review.googlesource.com/c/go/+/745840
Reviewed-by: Jorropo <jorropo.pgm@gmail.com>
Reviewed-by: Mark Freeman <markfreeman@google.com>
src/cmd/compile/internal/ssa/_gen/AMD64.rules
src/cmd/compile/internal/ssa/rewriteAMD64.go
test/fixedbugs/issue77613.go [new file with mode: 0644]

index b49e85b53cab8b14646151bc0e19e9e47bd0871c..956077d3924011b64df9653e508920a6dcdbf7f2 100644 (file)
 
 (MOVBload [off] {sym} (SB) _) && symIsRO(sym) => (MOVLconst [int32(read8(sym, int64(off)))])
 (MOVWload [off] {sym} (SB) _) && symIsRO(sym) => (MOVLconst [int32(read16(sym, int64(off), config.ctxt.Arch.ByteOrder))])
-(MOVLload [off] {sym} (SB) _) && symIsRO(sym) => (MOVLconst [int32(read32(sym, int64(off), config.ctxt.Arch.ByteOrder))])
+(MOVLload <t> [off] {sym} (SB) _) && symIsRO(sym) && is32BitInt(t) => (MOVLconst [int32(read32(sym, int64(off), config.ctxt.Arch.ByteOrder))])
+(MOVLload <t> [off] {sym} (SB) _) && symIsRO(sym) && is64BitInt(t) => (MOVQconst [int64(read32(sym, int64(off), config.ctxt.Arch.ByteOrder))])
 (MOVQload [off] {sym} (SB) _) && symIsRO(sym) => (MOVQconst [int64(read64(sym, int64(off), config.ctxt.Arch.ByteOrder))])
 (MOVBQSXload [off] {sym} (SB) _) && symIsRO(sym) => (MOVQconst [int64(int8(read8(sym, int64(off))))])
 (MOVWQSXload [off] {sym} (SB) _) && symIsRO(sym) => (MOVQconst [int64(int16(read16(sym, int64(off), config.ctxt.Arch.ByteOrder)))])
index b1b1c8404619a3b27afb57a55ec9ee2966481641..d005b15a5752640cd919512a742e076236be04d1 100644 (file)
@@ -16399,19 +16399,34 @@ func rewriteValueAMD64_OpAMD64MOVLload(v *Value) bool {
                v.AddArg(val)
                return true
        }
-       // match: (MOVLload [off] {sym} (SB) _)
-       // cond: symIsRO(sym)
+       // match: (MOVLload <t> [off] {sym} (SB) _)
+       // cond: symIsRO(sym) && is32BitInt(t)
        // result: (MOVLconst [int32(read32(sym, int64(off), config.ctxt.Arch.ByteOrder))])
        for {
+               t := v.Type
                off := auxIntToInt32(v.AuxInt)
                sym := auxToSym(v.Aux)
-               if v_0.Op != OpSB || !(symIsRO(sym)) {
+               if v_0.Op != OpSB || !(symIsRO(sym) && is32BitInt(t)) {
                        break
                }
                v.reset(OpAMD64MOVLconst)
                v.AuxInt = int32ToAuxInt(int32(read32(sym, int64(off), config.ctxt.Arch.ByteOrder)))
                return true
        }
+       // match: (MOVLload <t> [off] {sym} (SB) _)
+       // cond: symIsRO(sym) && is64BitInt(t)
+       // result: (MOVQconst [int64(read32(sym, int64(off), config.ctxt.Arch.ByteOrder))])
+       for {
+               t := v.Type
+               off := auxIntToInt32(v.AuxInt)
+               sym := auxToSym(v.Aux)
+               if v_0.Op != OpSB || !(symIsRO(sym) && is64BitInt(t)) {
+                       break
+               }
+               v.reset(OpAMD64MOVQconst)
+               v.AuxInt = int64ToAuxInt(int64(read32(sym, int64(off), config.ctxt.Arch.ByteOrder)))
+               return true
+       }
        return false
 }
 func rewriteValueAMD64_OpAMD64MOVLstore(v *Value) bool {
diff --git a/test/fixedbugs/issue77613.go b/test/fixedbugs/issue77613.go
new file mode 100644 (file)
index 0000000..df71ed4
--- /dev/null
@@ -0,0 +1,28 @@
+// run
+
+// Copyright 2026 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+       "strings"
+)
+
+func main() {
+       str1 := "你好世界"
+       if !strings.HasSuffix(str1, "世界") {
+               panic(1)
+       }
+
+       str2 := "こんにちは"
+       if !strings.HasSuffix(str2, "ちは") {
+               panic(2)
+       }
+
+       str3 := "спасибо"
+       if !strings.HasSuffix(str3, "ибо") {
+               panic(3)
+       }
+}