"math/bits"
"cmd/compile/internal/base"
- "cmd/internal/src"
)
const (
nword int32
}
-func NewBulk(nbit int32, count int32, pos src.XPos) Bulk {
+func NewBulk(nbit int32, count int32) Bulk {
nword := (nbit + wordBits - 1) / wordBits
size := int64(nword) * int64(count)
- if int64(int32(size*4)) != size*4 {
- base.FatalfAt(pos, "NewBulk too big: nbit=%d count=%d nword=%d size=%d", nbit, count, nword, size)
- }
return Bulk{
words: make([]uint32, size),
nbit: nbit,
import (
"cmp"
"fmt"
+ "math"
"os"
"slices"
"sort"
nblocks := int32(len(f.Blocks))
nvars := int32(len(vars))
- bulk := bitvec.NewBulk(nvars, nblocks*4, fn.Pos())
+ bulk := bitvec.NewBulk(nvars, nblocks*4)
for _, b := range f.Blocks {
be := lv.blockEffects(b)
loff := objw.Uint32(&liveSymTmp, 0, uint32(len(lv.stackMaps))) // number of bitmaps
loff = objw.Uint32(&liveSymTmp, loff, uint32(locals.N)) // number of bits in each bitmap
+ // Check for overflow before serializing stackmaps
+ checkStackmapOverflow(args, len(lv.stackMaps), lv.fn.Pos())
+ checkStackmapOverflow(locals, len(lv.stackMaps), lv.fn.Pos())
+
for _, live := range lv.stackMaps {
args.Clear()
locals.Clear()
if fn.Type().NumResults() > 0 {
nbitmap = 2
}
+
+ // defensive check: function arguments can't realistically be large enough for overflow here
+ checkStackmapOverflow(bv, nbitmap, fn.Pos())
+
lsym := base.Ctxt.Lookup(fn.LSym.Name + ".args_stackmap")
lsym.Set(obj.AttrLinkname, true) // allow args_stackmap referenced from assembly
off := objw.Uint32(lsym, 0, uint32(nbitmap))
objw.Global(lsym, int32(off), obj.RODATA|obj.LOCAL)
}
+
+// checkStackmapOverflow checks for potential overflow in runtime stackmap reading.
+// Runtime computes: n * ((nbit+7)/8) using int32 arithmetic.
+// See runtime.stackmapdata implementation.
+func checkStackmapOverflow(bv bitvec.BitVec, count int, pos src.XPos) {
+ if bv.N <= 0 || count <= 0 {
+ return
+ }
+ bytesPerBitVec := (int64(bv.N) + 7) >> 3
+ totalBytes := bytesPerBitVec * int64(count)
+ if totalBytes > math.MaxInt32 {
+ // runtime.stackmap has to support 64-bit values to avoid this restriction, see issue 77170
+ base.FatalfAt(pos, "liveness stackmaps are too large: nbit=%d count=%d totalBytes=%d exceeds MaxInt32", bv.N, count, totalBytes)
+ }
+}