aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Anthony Knyszek <mknyszek@google.com>2020-05-18 16:06:11 +0000
committerMichael Knyszek <mknyszek@google.com>2020-05-20 15:15:16 +0000
commitdfd613e0e4fd93ef945e9fbd6d42b79bcaf73905 (patch)
tree6e32f5f5f747a5eab4eea0e59d673ff1a36173c7 /src
parent4ec4a792f6e60c9c4f40a928650c66419ee0e446 (diff)
downloadgo-dfd613e0e4fd93ef945e9fbd6d42b79bcaf73905.tar.xz
runtime: don't use (addrRange).subtract in removeGreaterEqual
Currently in (*addrRanges).removeGreaterEqual we use (addrRange).subtract with a range from specified address to "infinity" which is supposed to be maxOffAddr. However, maxOffAddr is necessarily an inclusive bound on the address space, because on many platforms an exclusive bound would overflow back to 0. On some platforms like mips and mipsle, the address space is smaller than what's representable in a pointer, so if there's a range which hits the top of the address space (such as in the pageAlloc tests), the limit doesn't overflow, but maxOffAddr is inclusive, so any attempt to prune this range with (*addrRange).removeGreaterEqual causes a failure, since the range passed to subtract is contained within the address range which touches the top of the address space. Another problem with using subtract here is that addr and maxOffAddr.addr() may not be in the same segment which could cause makeAddrRange to panic. While this unlikely to happen, on some platforms such as Solaris it is possible. Fix these issues by not using subtract at all. Create a specific implementation of (addrRange).removeGreaterEqual which side-steps all of this by not having to worry about the top of the address space at all. Fixes #39128. Change-Id: Icd5b587b1a3d32a5681fb76cec4c001401f5756f Reviewed-on: https://go-review.googlesource.com/c/go/+/234457 Reviewed-by: Michael Pratt <mpratt@google.com> Reviewed-by: Austin Clements <austin@google.com> Reviewed-by: Cherry Zhang <cherryyz@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/runtime/mranges.go14
1 files changed, 13 insertions, 1 deletions
diff --git a/src/runtime/mranges.go b/src/runtime/mranges.go
index c2b8e7161c..e23d0778eb 100644
--- a/src/runtime/mranges.go
+++ b/src/runtime/mranges.go
@@ -69,6 +69,18 @@ func (a addrRange) subtract(b addrRange) addrRange {
return a
}
+// removeGreaterEqual removes all addresses in a greater than or equal
+// to addr and returns the new range.
+func (a addrRange) removeGreaterEqual(addr uintptr) addrRange {
+ if (offAddr{addr}).lessEqual(a.base) {
+ return addrRange{}
+ }
+ if a.limit.lessEqual(offAddr{addr}) {
+ return a
+ }
+ return makeAddrRange(a.base.addr(), addr)
+}
+
var (
// minOffAddr is the minimum address in the offset space, and
// it corresponds to the virtual address arenaBaseOffset.
@@ -281,7 +293,7 @@ func (a *addrRanges) removeGreaterEqual(addr uintptr) {
}
if r := a.ranges[pivot-1]; r.contains(addr) {
removed += r.size()
- r = r.subtract(makeAddrRange(addr, maxOffAddr.addr()))
+ r = r.removeGreaterEqual(addr)
if r.size() == 0 {
pivot--
} else {