From b27ddbadb5ecc869959d1affbd2d99812a23475f Mon Sep 17 00:00:00 2001 From: Nikolaus Schuetz Date: Thu, 13 Aug 2026 15:38:13 -0400 Subject: [PATCH] fix: guard LRUCache against non-positive capacity NewLRUCache and NewSyncLRUCache are exported, but calling Put on a cache created with a non-positive capacity panicked with a nil pointer dereference: the eviction path removes cache.tail.prev, which on an empty list is the head sentinel whose prev pointer is nil. Return early from Put when capacity is non-positive, since such a cache holds nothing. Add a regression test that fails (panics) before this change and passes after. --- util/util.go | 5 +++++ util/util_test.go | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/util/util.go b/util/util.go index d4e0f27d..57e98c5e 100644 --- a/util/util.go +++ b/util/util.go @@ -391,6 +391,11 @@ func (cache *LRUCache) Get(key interface{}) (value interface{}, ok bool) { } func (cache *LRUCache) Put(key interface{}, value interface{}) { + if cache.capacity <= 0 { + // A cache with non-positive capacity holds nothing, so there is nothing + // to store and no eviction to perform. + return + } n, ok := cache.m[key] if ok { cache.remove(n, false) diff --git a/util/util_test.go b/util/util_test.go index 45082b52..b25f9b83 100644 --- a/util/util_test.go +++ b/util/util_test.go @@ -232,6 +232,18 @@ func TestLRUCache(t *testing.T) { testCacheEqual(t, cache, []int{1, 3, 4}) } +func TestLRUCacheNonPositiveCapacity(t *testing.T) { + // A cache created with a non-positive capacity holds nothing and must not + // panic on Put. Previously the eviction path removed cache.tail.prev, which + // on an empty list is the head sentinel whose prev pointer is nil, causing a + // nil pointer dereference. + cache := NewLRUCache(0) + cache.Put("a", 1) + if _, ok := cache.Get("a"); ok { + t.Errorf("NewLRUCache(0): Get(\"a\") ok = true, want false (zero-capacity cache holds nothing)") + } +} + func testEscapeStringLiterals(t *testing.T, input string, expected string) { t.Helper() result := EscapeStringLiterals(input)