Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

panic out of range in bytes queue #148

Closed
codyohl opened this issue Jul 10, 2019 · 31 comments · Fixed by #236
Closed

panic out of range in bytes queue #148

codyohl opened this issue Jul 10, 2019 · 31 comments · Fixed by #236
Labels

Comments

@codyohl
Copy link

codyohl commented Jul 10, 2019

blockSize := int(binary.LittleEndian.Uint32(q.array[index : index+headerEntrySize]))

It appears there is a bounds check before the blockSize, but then there is an assumption that adding block size is not out of bounds.

@cristaloleg
Copy link
Collaborator

Hi, can you add a bit more details, please? What is the problem?

@codyohl
Copy link
Author

codyohl commented Jul 10, 2019

@cristaloleg, I can dig a little deeper into the bytes_queue to figure out what might be the right fix, but the underlying issue is that

return q.array[index+headerEntrySize : index+headerEntrySize+blockSize], blockSize, nil

results in a panic because index+headerEntrySize+blockSize >=len(q.array) .

There is a bounds check on L218 here:

if index+headerEntrySize >= len(q.array) {

but there is no bounds check for adding the blockSize to that. Does that make sense?

@cristaloleg
Copy link
Collaborator

Oh, finally I got it. I thought there is a problem on the line 222 as in the original message.

That's funny that there were no(???) panic before. I think somewhere in late 2017 I've checked this code and everything was fine. I might be wrong 😉

@codyohl
Copy link
Author

codyohl commented Jul 10, 2019

@cristaloleg it might be an uncommon edge case, or a misuse of the API somehow, but I did see this panic in logs using this code. If I have time, I can try to find a small reproducible test, it but it might be tough without enough knowledge about this code. I do experience this panic without changing this library, so some permutation of the usage of this API will cause the panic

@olivierperes
Copy link

@cristaloleg I obtain this panic while using an iterator to check all entries whose name match a given pattern and deleting them, while other processes are adding entries. It is also possible that two of these iterators work concurrently, but they cannot try to delete the same entries. Is this a supported pattern?

@janisz
Copy link
Collaborator

janisz commented Sep 25, 2019

@olivierperes Can you provide code to demonstrate this behavior?

@olivierperes
Copy link

This is the function that deletes entries. Unfortunately I cannot provide a unit test. My program can run for about 12 hours before the crash occurs.

// cleanCache deletes from the cache all elements whose name has the given prefix.
func cleanCache(prefix string) error {
	iterator := cache.Iterator()
	for iterator.SetNext() {
		entry, err := iterator.Value()
		if err != nil {
			return err
		}
		k := entry.Key()
		if strings.HasPrefix(k, prefix) {
			err := cache.Delete(k)
			if err != nil && err != bigcache.ErrEntryNotFound {
				return err
			}
		}
	}
	return nil
}

@janisz
Copy link
Collaborator

janisz commented Sep 25, 2019

My program can run for about 12 hours before the crash occurs.
That's important information. I suspect your program alocates more and more memory until it reaches

bigcache/config.go

Lines 23 to 27 in c00e2be

// HardMaxCacheSize is a limit for cache size in MB. Cache will not allocate more memory than this limit.
// It can protect application from consuming all available memory on machine, therefore from running OOM Killer.
// Default value is 0 which means unlimited size. When the limit is higher than 0 and reached then
// the oldest entries are overridden for the new ones.
HardMaxCacheSize int

So here

q.allocateAdditionalMemory(dataLen + headerEntrySize)

we may allocate less memory than we need

I think the bug may be here

func (q *BytesQueue) copy(data []byte, len int) {
q.tail += copy(q.array[q.tail:], data[:len])
}

We do not check if all data were succesfuly copied

@janisz
Copy link
Collaborator

janisz commented Sep 25, 2019

Here is small visualization https://storytime.dev/preview/5d8b85caddbb4e10b4566fc9

@olivierperes
Copy link

Hello @janisz. Just to be clear, is someone working on this or are you expecting a PR? In principle I would volunteer but in this case, it seems to require a very good knowledge of the code.

@janisz
Copy link
Collaborator

janisz commented Oct 1, 2019

I tired to reproduce this issue with approach I presented above but I can't do it. It's hard for me to figure out the order for inseritions/deletions to get invalid state.

@janisz
Copy link
Collaborator

janisz commented Oct 7, 2019

How about using https://github.com/dvyukov/go-fuzz to reproduce this bug. I came up with following piece of code. I have no experience in fuzzing so it might be totally wrong but at least we can iterate on this. We know bug is in Queue and my approach is to use random data to perform random operations on Queue (Push with random length and Pop).

package fuzz

import (
	"bytes"
	"encoding/binary"
	"io"

	. "github.com/allegro/bigcache/queue"
)

func Fuzz(data []byte) int {

	queue := NewBytesQueue(0, 4 * 1024 * 1024 * 1024, false)

	r := bytes.NewReader(data)
	for {
		push, n, err := nextMove(r)
		if err == io.EOF {
			return 1
		}
		if err != nil {
			panic(err)
		}
		if push {
			queue.Push(blob('a', int(n)))
		} else {
			queue.Pop()
		}
	}

	return 1
}

func nextMove(r io.Reader) (push bool, n int16, err error) {
	boolean := make([]byte, 1)
	_, err = r.Read(boolean)
	if err != nil {
		return false, n, err
	}
	if boolean[0] == 0 {
		return false, n, nil
	}
	integer := make([]byte, 16)
	_, err = r.Read(integer)
	if err != nil {
		return false, n, err
	}
	err = binary.Read(bytes.NewReader(integer), binary.BigEndian, &n)
	return true, n, err
}

func blob(char byte, len int) []byte {
	b := make([]byte, len)
	for index := range b {
		b[index] = char
	}
	return b
}

@janisz
Copy link
Collaborator

janisz commented Dec 2, 2019

This is similar to: https://github.com/janisz/bigcache/commit/e73c96d8b9c30e2f5247ce96521edbd62b5d096b/checks

goroutine 153 [running]:
github.com/allegro/bigcache/v2.readKeyFromEntry(0xc0287db076, 0x41b, 0x4f8a, 0xec9cb036dfa3401a, 0xc0287db076)
	/home/runner/work/bigcache/bigcache/encoding.go:51 +0x211
github.com/allegro/bigcache/v2.(*cacheShard).get(0xc013c59680, 0xc05661abf0, 0x9, 0xec9cb036dfa3401a, 0x0, 0x0, 0xc000165ec8, 0x512507, 0xc05661f680)
	/home/runner/work/bigcache/bigcache/shard.go:69 +0x120
github.com/allegro/bigcache/v2.(*BigCache).Get(0xc00015c000, 0xc05661abf0, 0x9, 0x1, 0x1, 0xc05661abf0, 0x9, 0x0)
	/home/runner/work/bigcache/bigcache/bigcache.go:118 +0x175
github.com/allegro/bigcache/v2.TestCacheDelRandomly.func3(0xc3500, 0xc00015c000, 0xc000110400, 0xc01429e5e0)
	/home/runner/work/bigcache/bigcache/bigcache_test.go:493 +0xd9
created by github.com/allegro/bigcache/v2.TestCacheDelRandomly
	/home/runner/work/bigcache/bigcache/bigcache_test.go:484 +0x264
exit status 2

@siennathesane
Copy link
Collaborator

I have no experience in fuzzing so it might be totally wrong but at least we can iterate on this.

I'm also not an expert, but you can prolly come up with a test case like you have already and then just loop over it N times with a fuzzer providing some data and then when it crashes, we'll see what happens.

/shrug

@janisz
Copy link
Collaborator

janisz commented Dec 2, 2019

@@ -46,6 +48,10 @@ func readTimestampFromEntry(data []byte) uint64 {
 func readKeyFromEntry(data []byte) string {
        length := binary.LittleEndian.Uint16(data[timestampSizeInBytes+hashSizeInBytes:])
 
+       if headersSizeInBytes+int(length) > len(data) {
+               panic(fmt.Sprintf("\n%s\n", hex.Dump(data)))
+       }
+
        // copy on read
        dst := make([]byte, length)
        copy(dst, data[headersSizeInBytes:headersSizeInBytes+length])
go test -run TestCacheDelRandomly -v -count 100
=== RUN   TestCacheDelRandomly
=== PAUSE TestCacheDelRandomly
=== CONT  TestCacheDelRandomly
2019/12/02 19:20:42 Allocated new queue in 1.179µs; Capacity: 2308 
2019/12/02 19:20:42 Allocated new queue in 10.236µs; Capacity: 4616 
2019/12/02 19:20:42 Allocated new queue in 9.476µs; Capacity: 9232 
2019/12/02 19:20:42 Allocated new queue in 18.23µs; Capacity: 18464 
2019/12/02 19:20:42 Allocated new queue in 43.117µs; Capacity: 36928 
2019/12/02 19:20:42 Allocated new queue in 37.135µs; Capacity: 73856 
2019/12/02 19:20:42 Allocated new queue in 90.396µs; Capacity: 147712 
2019/12/02 19:20:42 Allocated new queue in 113.411µs; Capacity: 295424 
2019/12/02 19:20:42 Allocated new queue in 191.364µs; Capacity: 590848 
2019/12/02 19:20:42 Allocated new queue in 351.637µs; Capacity: 1048576 
panic: 
00000000  6e 6e 6e 6e 6e 6e 6e 6e  6e 6e 6e 6e 6e 6e 6e 6e  |nnnnnnnnnnnnnnnn|
00000010  6e 6e 6e 6e 65 6b 65 79  31 38 34 b8 b8 b8 b8 b8  |nnnnekey184.....|
00000020  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000030  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000040  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000050  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000060  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000070  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000080  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000090  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000000a0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000000b0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000000c0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000000d0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000000e0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000000f0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000100  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000110  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000120  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000130  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000140  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000150  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000160  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000170  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000180  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000190  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000001a0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000001b0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000001c0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000001d0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000001e0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000001f0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000200  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000210  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000220  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000230  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000240  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000250  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000260  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000270  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000280  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000290  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000002a0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000002b0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000002c0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000002d0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000002e0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000002f0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000300  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000310  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000320  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000330  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000340  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000350  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000360  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000370  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000380  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000390  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000003a0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000003b0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000003c0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000003d0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000003e0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
000003f0  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000400  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8 b8 b8 b8 b8 b8  |................|
00000410  b8 b8 b8 b8 b8 b8 b8 b8  b8 b8 b8                 |...........|



goroutine 23 [running]:
github.com/allegro/bigcache/v2.readKeyFromEntry(0xc000343c32, 0x41b, 0x643ce, 0xec95a236df9d09a2, 0xc000343c32)
	/home/janisz/go/src/github.com/allegro/bigcache/encoding.go:52 +0x231
github.com/allegro/bigcache/v2.(*cacheShard).get(0xc0000f2000, 0xc00044c580, 0x9, 0xec95a236df9d09a2, 0xc00044c580, 0x9, 0x9, 0xc00044c580, 0xc0000b20d0)
	/home/janisz/go/src/github.com/allegro/bigcache/shard.go:69 +0xcd
github.com/allegro/bigcache/v2.(*BigCache).Get(0xc000092ea0, 0xc00044c580, 0x9, 0x1, 0x1, 0xc00044c580, 0x9, 0x0)
	/home/janisz/go/src/github.com/allegro/bigcache/bigcache.go:118 +0x8b
github.com/allegro/bigcache/v2.TestCacheDelRandomly.func3(0xc3500, 0xc000092ea0, 0xc0000dc100, 0xc0000a0110)
	/home/janisz/go/src/github.com/allegro/bigcache/bigcache_test.go:491 +0x96
created by github.com/allegro/bigcache/v2.TestCacheDelRandomly
	/home/janisz/go/src/github.com/allegro/bigcache/bigcache_test.go:482 +0x294
exit status 2
FAIL	github.com/allegro/bigcache/v2	1.059s

It looks like two entries can override each other.

go version
go version go1.13.4 linux/amd64

@janisz
Copy link
Collaborator

janisz commented Dec 2, 2019

@siennathesane
Copy link
Collaborator

It looks like two entries can override each other.

Race condition or bad locking?

@janisz
Copy link
Collaborator

janisz commented Dec 9, 2019

I think it could be a bad locking
@codyohlsen Do you experience same problems with the latest version of bigcache?

@siennathesane
Copy link
Collaborator

I saw this before the PR, and I would agree it's likely bad locking. Ideally, bigcache should deterministically lock on any operation, but I'm not really sure if that's reasonable.

@janisz
Copy link
Collaborator

janisz commented Jan 20, 2020

This just hit me

panic: runtime error: slice bounds out of range

goroutine 857 [running]:
panic(0x510f40, 0xc4200100c0)
	/usr/local/go/src/runtime/panic.go:500 +0x1a1
github.com/allegro/bigcache.(*cacheShard).get(0xc51e950360, 0xc4c8342220, 0x8, 0x20ab7654471937b6, 0x4b84c4, 0x10fdd43, 0xa, 0xc4c8342220, 0x8)
	/go/src/github.com/allegro/bigcache/shard.go:72 +0x68c
github.com/allegro/bigcache.(*BigCache).Get(0xc43579e1a0, 0xc4c8342220, 0x8, 0xc4c8353e00, 0x100, 0x100, 0x0, 0x0)
	/go/src/github.com/allegro/bigcache/bigcache.go:118 +0x92
github.com/allegro/bigcache.readFromCache.func1(0xc4df9d0000)
	/go/src/github.com/allegro/bigcache/bigcache_bench_test.go:160 +0x101
testing.(*B).RunParallel.func1(0xc4c82c8720, 0xc4c82c8718, 0xc4c82c8710, 0xc4fdfbc280, 0xc51e9520a0)
	/usr/local/go/src/testing/benchmark.go:598 +0xc4
created by testing.(*B).RunParallel
	/usr/local/go/src/testing/benchmark.go:599 +0x1a2

On BenchmarkReadFromCacheWithInfo/1-shards-4 signal: interrupt
Using Go go1.14beta1_linux_amd64 test was slightly modified I set HardMaxCacheSize: 16 * 1024,

@janisz
Copy link
Collaborator

janisz commented Jan 28, 2020

I prepared a test for this issue – unfortunately it's far from minimal but still reproducible example

func Test_issue_148(t *testing.T) {
	const n = 9000000
	var message = blob('a', 512)
	cache, _ := NewBigCache(Config{
		Shards:             1,
		LifeWindow:         time.Hour,
		MaxEntriesInWindow: 10,
		MaxEntrySize:       len(message) + 1,
		HardMaxCacheSize:   n >> 11,
	})
	for i := 0; i < n; i++ {
		err := cache.Set(strconv.Itoa(i), message)
		if err != nil {
			t.Fatal(err)
		}
	}

	wg := sync.WaitGroup{}
	wg.Add(n)
	for i := 0; i < n; i++ {
		go func() {
			cache.Get(strconv.Itoa(rand.Intn(n)))
			wg.Done()
		}()
	}
	wg.Wait()
}

@siennathesane
Copy link
Collaborator

The fact this feels like a transient locking issue is strange. I might try to take some time this week to work on it since I have some cycles.

@janisz
Copy link
Collaborator

janisz commented Jan 28, 2020

I found 3 problems:

  • Peek can return empty data without an error (this will cause panic when trying to decode entry)
    func (q *BytesQueue) peek(index int) ([]byte, int, error) {
    err := q.peekCheckErr(index)
    if err != nil {
    return nil, 0, err
    }
    blockSize := int(binary.LittleEndian.Uint32(q.array[index : index+headerEntrySize]))
    return q.array[index+headerEntrySize : index+headerEntrySize+blockSize], blockSize, nil
    }
  • We do not check if initial capacity is lower than hard max shard size
    func NewBytesQueue(initialCapacity int, maxCapacity int, verbose bool) *BytesQueue {
    return &BytesQueue{
    array: make([]byte, initialCapacity),
    capacity: initialCapacity,
    maxCapacity: maxCapacity,
    headerBuffer: make([]byte, headerEntrySize),
    tail: leftMarginIndex,
    head: leftMarginIndex,
    rightMargin: leftMarginIndex,
    verbose: verbose,
    initialCapacity: initialCapacity,
    }
    }
  • length + index can be bigger than len(data)

    bigcache/encoding.go

    Lines 46 to 54 in 0bde97d

    func readKeyFromEntry(data []byte) string {
    length := binary.LittleEndian.Uint16(data[timestampSizeInBytes+hashSizeInBytes:])
    // copy on read
    dst := make([]byte, length)
    copy(dst, data[headersSizeInBytes:headersSizeInBytes+length])
    return bytesToString(dst)
    }

@cristaloleg
Copy link
Collaborator

@janisz what is the status of the issue?

@cristaloleg cristaloleg added the bug label Jul 1, 2020
@janisz
Copy link
Collaborator

janisz commented Jul 1, 2020

We still need to fix it

@siennathesane
Copy link
Collaborator

I think #232 tentatively fixes this. I want to keep this open for a bit to see if we're still running across it.

@olivierperes @codyohlsen can you reproduce the issue on the latest commit?

@olivierperes
Copy link

can you reproduce the issue on the latest commit?

I changed job and no longer have access to the code that used BigCache, so I won’t be able to test.

@janisz janisz mentioned this issue Aug 14, 2020
@janisz
Copy link
Collaborator

janisz commented Aug 21, 2020

I think I found the problem. It's here

s.hashmap[hashedKey] = uint32(index)

On big queues we may overflow uint32 so for e.g. if we stored value under 4294968891 but in hashmap it's 1595 so when we try to read it we hit in the middle of random entry that is not int and result in panic.

I'll try to provide a patch for this

janisz added a commit to janisz/bigcache that referenced this issue Aug 21, 2020
There are posibility we run into a problem of int32 overflow.
To prevent this let's use uint64 everywhere.

https://github.com/allegro/bigcache/blob/21e5ca5c3d539f94e8dc563350acd97c5400154f/shard.go#L138

Fixes: allegro#148
janisz added a commit to janisz/bigcache that referenced this issue Aug 21, 2020
There are posibility we run into a problem of int32 overflow.
To prevent this let's use uint64 everywhere.

https://github.com/allegro/bigcache/blob/21e5ca5c3d539f94e8dc563350acd97c5400154f/shard.go#L138

Fixes: allegro#148
@codyohl
Copy link
Author

codyohl commented Aug 21, 2020 via email

janisz added a commit to janisz/bigcache that referenced this issue Oct 7, 2020
There are posibility we run into a problem of int32 overflow.
To prevent this let's use uint64 everywhere.

https://github.com/allegro/bigcache/blob/21e5ca5c3d539f94e8dc563350acd97c5400154f/shard.go#L138

Fixes: allegro#148
janisz added a commit to janisz/bigcache that referenced this issue Oct 8, 2020
There are posibility we run into a problem of int32 overflow.
To prevent this let's use uint64 everywhere.

https://github.com/allegro/bigcache/blob/21e5ca5c3d539f94e8dc563350acd97c5400154f/shard.go#L138

Fixes: allegro#148
janisz added a commit to janisz/bigcache that referenced this issue Oct 12, 2020
There are posibility we run into a problem of int32 overflow.
To prevent this let's use uint64 everywhere.

https://github.com/allegro/bigcache/blob/21e5ca5c3d539f94e8dc563350acd97c5400154f/shard.go#L138

Fixes: allegro#148
siennathesane pushed a commit that referenced this issue Nov 4, 2020
* Fix iterator styling issues (#247)

Issues reported in #246

* fix #160 (#246)

* Update to latest golang (#248)

Co-authored-by: Oleg Kovalov <[email protected]>

* inital prep for v3.

Signed-off-by: Mike Lloyd <[email protected]>

* Use uint64 intead of uint32

There are posibility we run into a problem of int32 overflow.
To prevent this let's use uint64 everywhere.

https://github.com/allegro/bigcache/blob/21e5ca5c3d539f94e8dc563350acd97c5400154f/shard.go#L138

Fixes: #148

* Fix CI

* Do not run on 1.13

* Do not run long test

* Optimze append (#249)

* Add Benchmark for append

* Optimize Append and halve byte copies

* Optimize Append by reducing allocs

* Optimize Append by reducing allocs

* Reduces allocs from test construct

Co-authored-by: Fabian Gärtner <[email protected]>

Co-authored-by: S@P <[email protected]>
Co-authored-by: Oleg Kovalov <[email protected]>
Co-authored-by: Mike Lloyd <[email protected]>
Co-authored-by: Fabianexe <[email protected]>
Co-authored-by: Fabian Gärtner <[email protected]>
siennathesane pushed a commit that referenced this issue Nov 4, 2020
* Fix iterator styling issues (#247)

Issues reported in #246

* fix #160 (#246)

* Update to latest golang (#248)

Co-authored-by: Oleg Kovalov <[email protected]>

* inital prep for v3.

Signed-off-by: Mike Lloyd <[email protected]>

* Use uint64 intead of uint32

There are posibility we run into a problem of int32 overflow.
To prevent this let's use uint64 everywhere.

https://github.com/allegro/bigcache/blob/21e5ca5c3d539f94e8dc563350acd97c5400154f/shard.go#L138

Fixes: #148

* Fix CI

* Do not run on 1.13

* Do not run long test

* Optimze append (#249)

* Add Benchmark for append

* Optimize Append and halve byte copies

* Optimize Append by reducing allocs

* Optimize Append by reducing allocs

* Reduces allocs from test construct

Co-authored-by: Fabian Gärtner <[email protected]>

Co-authored-by: S@P <[email protected]>
Co-authored-by: Oleg Kovalov <[email protected]>
Co-authored-by: Mike Lloyd <[email protected]>
Co-authored-by: Fabianexe <[email protected]>
Co-authored-by: Fabian Gärtner <[email protected]>
@janisz
Copy link
Collaborator

janisz commented Sep 8, 2021

@codyohl @cristaloleg can we close it. It was fixed by #236

@codyohl
Copy link
Author

codyohl commented Sep 14, 2021

@janisz Yes, i don't observe this anymore. I'm all good with closing!

@codyohl codyohl closed this as completed Sep 14, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants