From 9eadcacf978ceed12800d2c1533e5d8a811d863d Mon Sep 17 00:00:00 2001 From: Michael Hoang Date: Sun, 10 May 2026 13:46:30 +0200 Subject: [PATCH] fix: use-after-free on bbolt mmap-backed cache slice CachedFormatSignature held a bucket.Get slice past its tx; a concurrent db.Update grow unmaps and remaps the file so a later bytes.Equal in scheduler.submit faulted. Possibly the cause of #548 --- walk/cached.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/walk/cached.go b/walk/cached.go index 2d5657a3..438f318b 100644 --- a/walk/cached.go +++ b/walk/cached.go @@ -1,6 +1,7 @@ package walk import ( + "bytes" "context" "errors" "fmt" @@ -102,7 +103,9 @@ func (c *CachedReader) Read(ctx context.Context, files []*File) (n int, err erro for i := range n { file := files[i] - file.CachedFormatSignature = bucket.Get([]byte(file.RelPath)) + // Avoid use-after-free as bucket.Get returns a slice that is only valid for + // the lifetime of this transaction. + file.CachedFormatSignature = bytes.Clone(bucket.Get([]byte(file.RelPath))) // set a release function which inserts this file into the update channel file.AddReleaseFunc(func(ctx context.Context) error {