Skip to content

Commit

Permalink
fix ring buffer bugs
Browse files Browse the repository at this point in the history
Bug in Write fixed regarding OOB access to user buffer. Also found edge case where if end==off after a write then following Read fails with 0 bytes read and no error returned
  • Loading branch information
soypat committed May 9, 2024
1 parent ff83b37 commit a6350ce
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 2 deletions.
47 changes: 47 additions & 0 deletions stacks/intern_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,53 @@ func TestRing2(t *testing.T) {
}
}

func TestRing_findcrash(t *testing.T) {
const maxsize = 33
const ntests = 800000
r := ring{
buf: make([]byte, maxsize*6),
}
rng := rand.New(rand.NewSource(0))
data := make([]byte, maxsize)

for i := 0; i < ntests; i++ {
free := r.Free()
if free < 0 {
t.Fatal("free < 0")
}
if rng.Intn(2) == 0 {
l := max(rng.Intn(len(data)), 1)
if l > free {
continue // Buffer full.
}
n, err := r.Write(data[:l])
expectFree := free - n
free = r.Free()
if n != l {
t.Fatal(i, "write failed", n, l, err)
} else if expectFree != free {
t.Fatal(i, "free not updated correctly", expectFree, free)
}
}
buffered := r.Buffered()
if buffered < 0 {
t.Fatal("buffered < 0")
}
if rng.Intn(2) == 0 {
l := max(rng.Intn(len(data)), 1)
n, err := r.Read(data[:l])
expectRead := min(buffered, l)
expectBuffered := buffered - n
buffered = r.Buffered()
if n != expectRead {
t.Fatal(i, "read failed", n, l, expectRead, err)
} else if buffered != expectBuffered {
t.Fatal(i, "buffered not updated correctly", expectBuffered, buffered)
}
}
}
}

func testRing1_loopback(t *testing.T, rng *rand.Rand, ringbuf, data, auxbuf []byte) bool {
if len(data) > len(ringbuf) || len(data) > len(auxbuf) {
panic("invalid ringbuf or data")
Expand Down
4 changes: 2 additions & 2 deletions stacks/ring.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func (r *ring) Write(b []byte) (int, error) {
n := copy(r.buf[r.end:], b)
r.end += n
if n < len(b) {
n2 := copy(r.buf, b[n:r.off])
n2 := copy(r.buf, b[n:])
r.end = n2
n += n2
}
Expand All @@ -44,7 +44,7 @@ func (r *ring) Read(b []byte) (int, error) {
return 0, io.EOF
}

if r.end >= r.off {
if r.end > r.off {
// start off end len(buf)
// | sfree | used | efree |
n := copy(b, r.buf[r.off:r.end])
Expand Down

0 comments on commit a6350ce

Please sign in to comment.