From b8f38321d4ff69af17eb7a050d0d05fb94e2a773 Mon Sep 17 00:00:00 2001 From: cuiweixie Date: Mon, 6 Apr 2026 09:25:40 +0800 Subject: [PATCH] cmd/trace: fix fillPCs overflow with panic --- src/cmd/trace/pprof.go | 9 +++++++-- src/cmd/trace/pprof_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/cmd/trace/pprof.go b/src/cmd/trace/pprof.go index b472ffa759114b..715b17c789010d 100644 --- a/src/cmd/trace/pprof.go +++ b/src/cmd/trace/pprof.go @@ -319,10 +319,15 @@ func (m *stackMap) profile() []traceviewer.ProfileRecord { // pcsForStack extracts the first pprofMaxStack PCs from stack into pcs. func pcsForStack(stack trace.Stack, pcs *[pprofMaxStack]uint64) { - for i, frame := range slices.Collect(stack.Frames()) { - pcs[i] = frame.PC + fillPCs(slices.Collect(stack.Frames()), pcs) +} + +// fillPCs writes frame PCs into pcs, stopping at len(pcs). +func fillPCs(frames []trace.StackFrame, pcs *[pprofMaxStack]uint64) { + for i, frame := range frames { if i >= len(pcs) { break } + pcs[i] = frame.PC } } diff --git a/src/cmd/trace/pprof_test.go b/src/cmd/trace/pprof_test.go index 6d18e7d5d16a0f..0fd375fd4be822 100644 --- a/src/cmd/trace/pprof_test.go +++ b/src/cmd/trace/pprof_test.go @@ -14,6 +14,7 @@ import ( "testing/synctest" "time" + itrace "internal/trace" "internal/trace/testtrace" ) @@ -81,6 +82,30 @@ func TestSyscallProfile74850(t *testing.T) { } } +// Regression test: fillPCs (used by pcsForStack) must not panic when the +// number of frames exceeds pprofMaxStack (128). Before the fix, pcs[i] was +// written before checking i >= len(pcs), causing an index-out-of-range panic. +func TestFillPCsOverflow(t *testing.T) { + var pcs [pprofMaxStack]uint64 + + // Build a slice of frames larger than pprofMaxStack. + n := pprofMaxStack + 10 + frames := make([]itrace.StackFrame, n) + for i := range frames { + frames[i].PC = uint64(0x1000 + i) + } + + // This must not panic. + fillPCs(frames, &pcs) + + // Verify the first pprofMaxStack entries were written correctly. + for i := 0; i < pprofMaxStack; i++ { + if pcs[i] != uint64(0x1000+i) { + t.Errorf("pcs[%d] = %#x, want %#x", i, pcs[i], 0x1000+i) + } + } +} + func stat(t *testing.T) { _, err := os.Stat(".") if err != nil {