Skip to content

Commit 2c05ba4

Browse files
committed
runtime: top align tinyallocs in race mode
Top align allocations in tinyalloc buckets when in race mode. This will make checkptr checks more reliable, because any code that modifies a pointer past the end of the object will trigger a checkptr error. No test, because we need -race for this to actually kick in. We could add it to the race detector tests, but the race detector tests are all geared towards race detector reports, not checkptr reports. Mucking with parsing reports is more than a test is worth. Fixes #38872 Change-Id: Ie56f0fbd1a9385539f6631fd1ac40c3de5600154 Reviewed-on: https://go-review.googlesource.com/c/go/+/315029 Trust: Keith Randall <[email protected]> Run-TryBot: Keith Randall <[email protected]> Reviewed-by: Cuong Manh Le <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]> TryBot-Result: Go Bot <[email protected]>
1 parent 32dbaac commit 2c05ba4

File tree

3 files changed

+26
-1
lines changed

3 files changed

+26
-1
lines changed

src/runtime/export_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,3 +1267,5 @@ func GCTestIsReachable(ptrs ...unsafe.Pointer) (mask uint64) {
12671267
func GCTestPointerClass(p unsafe.Pointer) string {
12681268
return gcTestPointerClass(p)
12691269
}
1270+
1271+
const Raceenabled = raceenabled

src/runtime/malloc.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1047,7 +1047,8 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
10471047
(*[2]uint64)(x)[1] = 0
10481048
// See if we need to replace the existing tiny block with the new one
10491049
// based on amount of remaining free space.
1050-
if size < c.tinyoffset || c.tiny == 0 {
1050+
if !raceenabled && (size < c.tinyoffset || c.tiny == 0) {
1051+
// Note: disabled when race detector is on, see comment near end of this function.
10511052
c.tiny = uintptr(x)
10521053
c.tinyoffset = size
10531054
}
@@ -1165,6 +1166,22 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
11651166
}
11661167
}
11671168

1169+
if raceenabled && noscan && dataSize < maxTinySize {
1170+
// Pad tinysize allocations so they are aligned with the end
1171+
// of the tinyalloc region. This ensures that any arithmetic
1172+
// that goes off the top end of the object will be detectable
1173+
// by checkptr (issue 38872).
1174+
// Note that we disable tinyalloc when raceenabled for this to work.
1175+
// TODO: This padding is only performed when the race detector
1176+
// is enabled. It would be nice to enable it if any package
1177+
// was compiled with checkptr, but there's no easy way to
1178+
// detect that (especially at compile time).
1179+
// TODO: enable this padding for all allocations, not just
1180+
// tinyalloc ones. It's tricky because of pointer maps.
1181+
// Maybe just all noscan objects?
1182+
x = add(x, size-dataSize)
1183+
}
1184+
11681185
return x
11691186
}
11701187

src/runtime/malloc_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,9 @@ func TestStringConcatenationAllocs(t *testing.T) {
154154
}
155155

156156
func TestTinyAlloc(t *testing.T) {
157+
if runtime.Raceenabled {
158+
t.Skip("tinyalloc suppressed when running in race mode")
159+
}
157160
const N = 16
158161
var v [N]unsafe.Pointer
159162
for i := range v {
@@ -182,6 +185,9 @@ type obj12 struct {
182185
}
183186

184187
func TestTinyAllocIssue37262(t *testing.T) {
188+
if runtime.Raceenabled {
189+
t.Skip("tinyalloc suppressed when running in race mode")
190+
}
185191
// Try to cause an alignment access fault
186192
// by atomically accessing the first 64-bit
187193
// value of a tiny-allocated object.

0 commit comments

Comments
 (0)