[dev.boringcrypto.go1.17] all: merge go1.17.13 into dev.boringcrypto.go1.17

Change-Id: Iaf4f2cb506aab9e22a5df5b937c38fc108f1e1c1
diff --git a/src/cmd/compile/internal/ssa/loopbce.go b/src/cmd/compile/internal/ssa/loopbce.go
index 5a4bc1d..fd03efb 100644
--- a/src/cmd/compile/internal/ssa/loopbce.go
+++ b/src/cmd/compile/internal/ssa/loopbce.go
@@ -159,6 +159,13 @@
 			step = -step
 		}
 
+		if flags&indVarMaxInc != 0 && max.Op == OpConst64 && max.AuxInt+step < max.AuxInt {
+			// For a <= comparison, we need to make sure that a value equal to
+			// max can be incremented without overflowing.
+			// (For a < comparison, the %step check below ensures no overflow.)
+			continue
+		}
+
 		// Up to now we extracted the induction variable (ind),
 		// the increment delta (inc), the temporary sum (nxt),
 		// the mininum value (min) and the maximum value (max).
diff --git a/src/cmd/compile/internal/walk/complit.go b/src/cmd/compile/internal/walk/complit.go
index abd920d..1f288d2 100644
--- a/src/cmd/compile/internal/walk/complit.go
+++ b/src/cmd/compile/internal/walk/complit.go
@@ -621,6 +621,12 @@
 		// not a special composite literal assignment
 		return false
 	}
+	if x.Addrtaken() {
+		// If x is address-taken, the RHS may (implicitly) uses LHS.
+		// Not safe to do a special composite literal assignment
+		// (which may expand to multiple assignments).
+		return false
+	}
 
 	switch n.Y.Op() {
 	default:
@@ -629,7 +635,7 @@
 
 	case ir.OSTRUCTLIT, ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT:
 		if ir.Any(n.Y, func(y ir.Node) bool { return ir.Uses(y, x) }) {
-			// not a special composite literal assignment
+			// not safe to do a special composite literal assignment if RHS uses LHS.
 			return false
 		}
 		anylit(n.Y, n.X, init)
diff --git a/src/math/big/floatmarsh.go b/src/math/big/floatmarsh.go
index d1c1dab..990e085 100644
--- a/src/math/big/floatmarsh.go
+++ b/src/math/big/floatmarsh.go
@@ -8,6 +8,7 @@
 
 import (
 	"encoding/binary"
+	"errors"
 	"fmt"
 )
 
@@ -67,6 +68,9 @@
 		*z = Float{}
 		return nil
 	}
+	if len(buf) < 6 {
+		return errors.New("Float.GobDecode: buffer too small")
+	}
 
 	if buf[0] != floatGobVersion {
 		return fmt.Errorf("Float.GobDecode: encoding version %d not supported", buf[0])
@@ -83,6 +87,9 @@
 	z.prec = binary.BigEndian.Uint32(buf[2:])
 
 	if z.form == finite {
+		if len(buf) < 10 {
+			return errors.New("Float.GobDecode: buffer too small for finite form float")
+		}
 		z.exp = int32(binary.BigEndian.Uint32(buf[6:]))
 		z.mant = z.mant.setBytes(buf[10:])
 	}
diff --git a/src/math/big/floatmarsh_test.go b/src/math/big/floatmarsh_test.go
index c056d78..401f45a 100644
--- a/src/math/big/floatmarsh_test.go
+++ b/src/math/big/floatmarsh_test.go
@@ -137,3 +137,15 @@
 		}
 	}
 }
+
+func TestFloatGobDecodeShortBuffer(t *testing.T) {
+	for _, tc := range [][]byte{
+		[]byte{0x1, 0x0, 0x0, 0x0},
+		[]byte{0x1, 0xfa, 0x0, 0x0, 0x0, 0x0},
+	} {
+		err := NewFloat(0).GobDecode(tc)
+		if err == nil {
+			t.Error("expected GobDecode to return error for malformed input")
+		}
+	}
+}
diff --git a/src/math/big/ratmarsh.go b/src/math/big/ratmarsh.go
index fbc7b60..56102e8 100644
--- a/src/math/big/ratmarsh.go
+++ b/src/math/big/ratmarsh.go
@@ -45,12 +45,18 @@
 		*z = Rat{}
 		return nil
 	}
+	if len(buf) < 5 {
+		return errors.New("Rat.GobDecode: buffer too small")
+	}
 	b := buf[0]
 	if b>>1 != ratGobVersion {
 		return fmt.Errorf("Rat.GobDecode: encoding version %d not supported", b>>1)
 	}
 	const j = 1 + 4
 	i := j + binary.BigEndian.Uint32(buf[j-4:j])
+	if len(buf) < int(i) {
+		return errors.New("Rat.GobDecode: buffer too small")
+	}
 	z.a.neg = b&1 != 0
 	z.a.abs = z.a.abs.setBytes(buf[j:i])
 	z.b.abs = z.b.abs.setBytes(buf[i:])
diff --git a/src/math/big/ratmarsh_test.go b/src/math/big/ratmarsh_test.go
index 351d109..55a9878 100644
--- a/src/math/big/ratmarsh_test.go
+++ b/src/math/big/ratmarsh_test.go
@@ -123,3 +123,15 @@
 		}
 	}
 }
+
+func TestRatGobDecodeShortBuffer(t *testing.T) {
+	for _, tc := range [][]byte{
+		[]byte{0x2},
+		[]byte{0x2, 0x0, 0x0, 0x0, 0xff},
+	} {
+		err := NewRat(1, 2).GobDecode(tc)
+		if err == nil {
+			t.Error("expected GobDecode to return error for malformed input")
+		}
+	}
+}
diff --git a/src/runtime/time.go b/src/runtime/time.go
index 517a493..70e21d4 100644
--- a/src/runtime/time.go
+++ b/src/runtime/time.go
@@ -390,7 +390,11 @@
 	if i == 0 {
 		updateTimer0When(pp)
 	}
-	atomic.Xadd(&pp.numTimers, -1)
+	n := atomic.Xadd(&pp.numTimers, -1)
+	if n == 0 {
+		// If there are no timers, then clearly none are modified.
+		atomic.Store64(&pp.timerModifiedEarliest, 0)
+	}
 	return smallestChanged
 }
 
@@ -414,7 +418,11 @@
 		siftdownTimer(pp.timers, 0)
 	}
 	updateTimer0When(pp)
-	atomic.Xadd(&pp.numTimers, -1)
+	n := atomic.Xadd(&pp.numTimers, -1)
+	if n == 0 {
+		// If there are no timers, then clearly none are modified.
+		atomic.Store64(&pp.timerModifiedEarliest, 0)
+	}
 }
 
 // modtimer modifies an existing timer.
diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go
index 814c323..de59349 100644
--- a/src/runtime/traceback.go
+++ b/src/runtime/traceback.go
@@ -116,6 +116,7 @@
 	}
 	waspanic := false
 	cgoCtxt := gp.cgoCtxt
+	stack := gp.stack
 	printing := pcbuf == nil && callback == nil
 
 	// If the PC is zero, it's likely a nil function call.
@@ -134,7 +135,7 @@
 	if !f.valid() {
 		if callback != nil || printing {
 			print("runtime: unknown pc ", hex(frame.pc), "\n")
-			tracebackHexdump(gp.stack, &frame, 0)
+			tracebackHexdump(stack, &frame, 0)
 		}
 		if callback != nil {
 			throw("unknown pc")
@@ -194,12 +195,15 @@
 					frame.fn = findfunc(frame.pc)
 					f = frame.fn
 					flag = f.flag
+					frame.lr = gp.m.curg.sched.lr
 					frame.sp = gp.m.curg.sched.sp
+					stack = gp.m.curg.stack
 					cgoCtxt = gp.m.curg.cgoCtxt
 				case funcID_systemstack:
 					// systemstack returns normally, so just follow the
 					// stack transition.
 					frame.sp = gp.m.curg.sched.sp
+					stack = gp.m.curg.stack
 					cgoCtxt = gp.m.curg.cgoCtxt
 					flag &^= funcFlag_SPWRITE
 				}
@@ -268,7 +272,7 @@
 				}
 				if callback != nil || doPrint {
 					print("runtime: unexpected return pc for ", funcname(f), " called from ", hex(frame.lr), "\n")
-					tracebackHexdump(gp.stack, &frame, lrPtr)
+					tracebackHexdump(stack, &frame, lrPtr)
 				}
 				if callback != nil {
 					throw("unknown caller pc")
@@ -497,6 +501,13 @@
 			break
 		}
 
+		if frame.pc == frame.lr && frame.sp == frame.fp {
+			// If the next frame is identical to the current frame, we cannot make progress.
+			print("runtime: traceback stuck. pc=", hex(frame.pc), " sp=", hex(frame.sp), "\n")
+			tracebackHexdump(stack, &frame, frame.sp)
+			throw("traceback stuck")
+		}
+
 		// Unwind to next frame.
 		frame.fn = flr
 		frame.pc = frame.lr
diff --git a/test/fixedbugs/issue52953.go b/test/fixedbugs/issue52953.go
new file mode 100644
index 0000000..2085e4e
--- /dev/null
+++ b/test/fixedbugs/issue52953.go
@@ -0,0 +1,29 @@
+// run
+
+// Copyright 2022 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.
+
+// Issue 52953: miscompilation for composite literal assignment
+// when LHS is address-taken.
+
+package main
+
+type T struct {
+	Field1 bool
+}
+
+func main() {
+	var ret T
+	ret.Field1 = true
+	var v *bool = &ret.Field1
+	ret = T{Field1: *v}
+	check(ret.Field1)
+}
+
+//go:noinline
+func check(b bool) {
+	if !b {
+		panic("FAIL")
+	}
+}
diff --git a/test/fixedbugs/issue53600.go b/test/fixedbugs/issue53600.go
new file mode 100644
index 0000000..fd3a9e5
--- /dev/null
+++ b/test/fixedbugs/issue53600.go
@@ -0,0 +1,42 @@
+// run
+
+// Copyright 2022 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 "math"
+
+func main() {
+	f()
+	g()
+	h()
+}
+func f() {
+	for i := int64(math.MaxInt64); i <= math.MaxInt64; i++ {
+		if i < 0 {
+			println("done")
+			return
+		}
+		println(i, i < 0)
+	}
+}
+func g() {
+	for i := int64(math.MaxInt64) - 1; i <= math.MaxInt64; i++ {
+		if i < 0 {
+			println("done")
+			return
+		}
+		println(i, i < 0)
+	}
+}
+func h() {
+	for i := int64(math.MaxInt64) - 2; i <= math.MaxInt64; i += 2 {
+		if i < 0 {
+			println("done")
+			return
+		}
+		println(i, i < 0)
+	}
+}
diff --git a/test/fixedbugs/issue53600.out b/test/fixedbugs/issue53600.out
new file mode 100644
index 0000000..5590c7d
--- /dev/null
+++ b/test/fixedbugs/issue53600.out
@@ -0,0 +1,8 @@
+9223372036854775807 false
+done
+9223372036854775806 false
+9223372036854775807 false
+done
+9223372036854775805 false
+9223372036854775807 false
+done