From 33299235ceed03fb6e1e919eb79f65ddea67eaf5 Mon Sep 17 00:00:00 2001 From: Rohan Verma Date: Wed, 6 Nov 2024 12:05:54 +0530 Subject: [PATCH] fix: prevent buffer reuse in async mode for Put method If the mode is async, we need to copy request Blob to prevent fasthttp from reusing the buffer since we are going to use the buffer in a separate goroutine beyond the scope of the current request. --- fastcache.go | 4 +++- stores/goredis/redis.go | 8 ++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/fastcache.go b/fastcache.go index 8a3268e..c47ea61 100644 --- a/fastcache.go +++ b/fastcache.go @@ -77,7 +77,9 @@ type Item struct { ContentType string Compression string ETag string - Blob []byte + // If the Blob is used beyond the scope of the request, it should be copied. + // Such as when the cache is written asynchronously. + Blob []byte } // Store represents a backend data store where bytes are cached. Individual diff --git a/stores/goredis/redis.go b/stores/goredis/redis.go index 614966f..4376e03 100644 --- a/stores/goredis/redis.go +++ b/stores/goredis/redis.go @@ -169,6 +169,14 @@ type putReq struct { // Put sets a value to given session but stored only on commit func (s *Store) Put(namespace, group, uri string, b fastcache.Item, ttl time.Duration) error { if s.config.Async { + // In async mode, we need to copy b.Blob to prevent fasthttp from reusing + // the buffer, as we will use the buffer in a separate goroutine beyond + // the scope of the current request. + blobCopy := make([]byte, len(b.Blob)) + copy(blobCopy, b.Blob) + b.Blob = blobCopy + + // Send the put request to the async buffer channel. s.putBuf <- putReq{namespace, group, uri, b, ttl} return nil }