From d852b42c66e4989542275b828af4846c333841f3 Mon Sep 17 00:00:00 2001 From: rabbitstack Date: Fri, 23 Jan 2026 19:38:37 +0100 Subject: [PATCH] fix: Safe slice mutation during iteration Mutating the slice while iterating leads to nasty side effects as the loop keeps evaluating the original slice header so removals don't shrink the loop bounds. --- internal/etw/processors/fs_windows.go | 13 ++++++++----- pkg/event/stackwalk.go | 10 +++++++--- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/internal/etw/processors/fs_windows.go b/internal/etw/processors/fs_windows.go index f8737868c..96a654a5b 100644 --- a/internal/etw/processors/fs_windows.go +++ b/internal/etw/processors/fs_windows.go @@ -20,6 +20,9 @@ package processors import ( "expvar" + "sync" + "time" + "github.com/rabbitstack/fibratus/pkg/config" "github.com/rabbitstack/fibratus/pkg/event" "github.com/rabbitstack/fibratus/pkg/event/params" @@ -31,8 +34,6 @@ import ( "github.com/rabbitstack/fibratus/pkg/util/va" "golang.org/x/sys/windows" "golang.org/x/time/rate" - "sync" - "time" ) var ( @@ -371,11 +372,13 @@ func (f *fsProcessor) purge() { // evict unmatched stack traces for id, q := range f.buckets { - for i, evt := range q { - if time.Since(evt.Timestamp) > time.Second*30 { - f.buckets[id] = append(q[:i], q[i+1:]...) + s := q[:0] + for _, evt := range q { + if time.Since(evt.Timestamp) <= time.Second*30 { + s = append(s, evt) } } + f.buckets[id] = s } f.mu.Unlock() diff --git a/pkg/event/stackwalk.go b/pkg/event/stackwalk.go index c54bde0d7..d785c9cca 100644 --- a/pkg/event/stackwalk.go +++ b/pkg/event/stackwalk.go @@ -160,8 +160,9 @@ func (s *StackwalkDecorator) Pop(e *Event) *Event { if !proc.IsCreateProcess() && proc.Params.MustGetPid() != pid { continue } - s.buckets[ev.StackID()] = append(qu[:i], qu[i+1:]...) + qu = append(qu[:i], qu[i+1:]...) } + s.buckets[ev.StackID()] = qu } } @@ -209,16 +210,18 @@ func (s *StackwalkDecorator) flush() []error { errs := make([]error, 0) for id, q := range s.buckets { - for i, evt := range q { + n := q[:0] + for _, evt := range q { if time.Since(evt.Timestamp) < maxQueueTTLPeriod { + n = append(n, evt) continue } + stackwalkFlushes.Add(1) err := s.q.push(evt) if err != nil { errs = append(errs, err) } - s.buckets[id] = append(q[:i], q[i+1:]...) if stackwalkEnqueued.Value() > 0 { stackwalkEnqueued.Add(-1) } @@ -227,6 +230,7 @@ func (s *StackwalkDecorator) flush() []error { } stackwalkFlushesEvents.Add(evt.Name, 1) } + s.buckets[id] = n } return errs