Skip to content

Commit 20e22d4

Browse files
niaowdeadprogram
authored andcommitted
runtime (gc_blocks.go): clear full size of allocation
This fixes a bug where runtime.alloc would not clear the padding from rounding the allocation up to a multiple of the block size. The GC still has to scan this, and this could result in permanent false positives (and therefore memory leaks). It also handles overflow in the size calculation.
1 parent 9118e91 commit 20e22d4

File tree

2 files changed

+18
-9
lines changed

2 files changed

+18
-9
lines changed

builder/sizes_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ func TestBinarySize(t *testing.T) {
4242
// This is a small number of very diverse targets that we want to test.
4343
tests := []sizeTest{
4444
// microcontrollers
45-
{"hifive1b", "examples/echo", 3884, 280, 0, 2268},
46-
{"microbit", "examples/serial", 2844, 360, 8, 2272},
47-
{"wioterminal", "examples/pininterrupt", 7349, 1491, 116, 6912},
45+
{"hifive1b", "examples/echo", 3896, 280, 0, 2268},
46+
{"microbit", "examples/serial", 2860, 360, 8, 2272},
47+
{"wioterminal", "examples/pininterrupt", 7361, 1491, 116, 6912},
4848

4949
// TODO: also check wasm. Right now this is difficult, because
5050
// wasm binaries are run through wasm-opt and therefore the

src/runtime/gc_blocks.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -311,22 +311,31 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
311311
return unsafe.Pointer(&zeroSizedAlloc)
312312
}
313313

314+
if interrupt.In() {
315+
runtimePanicAt(returnAddress(0), "heap alloc in interrupt")
316+
}
317+
318+
// Round the size up to a multiple of blocks.
319+
rawSize := size
320+
size += bytesPerBlock - 1
314321
if preciseHeap {
322+
// Add space for the layout.
315323
size += align(unsafe.Sizeof(layout))
316324
}
317-
318-
if interrupt.In() {
319-
runtimePanicAt(returnAddress(0), "heap alloc in interrupt")
325+
if size < rawSize {
326+
// The size overflowed.
327+
runtimePanicAt(returnAddress(0), "out of memory")
320328
}
329+
neededBlocks := size / bytesPerBlock
330+
size = neededBlocks * bytesPerBlock
321331

322332
// Make sure there are no concurrent allocations. The heap is not currently
323333
// designed for concurrent alloc/GC.
324334
gcLock.Lock()
325335

326-
gcTotalAlloc += uint64(size)
336+
// Update the total allocation counters.
337+
gcTotalAlloc += uint64(rawSize)
327338
gcMallocs++
328-
329-
neededBlocks := (size + (bytesPerBlock - 1)) / bytesPerBlock
330339
gcTotalBlocks += uint64(neededBlocks)
331340

332341
// Continue looping until a run of free blocks has been found that fits the

0 commit comments

Comments
 (0)