Skip to content

Commit

Permalink
Fix bad recursive reads in piece resource chunks ReadAt
Browse files Browse the repository at this point in the history
It would always read from the first chunk, and scan across io.EOF until it hit the right chunk.
  • Loading branch information
anacrolix committed Jul 12, 2024
1 parent f22cf7d commit 5cbffbc
Showing 1 changed file with 33 additions and 16 deletions.
49 changes: 33 additions & 16 deletions storage/piece-resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,25 +267,42 @@ type chunk struct {

type chunks []chunk

func (me chunks) ReadAt(b []byte, off int64) (int, error) {
for {
if len(me) == 0 {
return 0, io.EOF
}
if me[0].offset <= off {
break
}
me = me[1:]
func (me chunks) ReadAt(b []byte, off int64) (n int, err error) {
i := sort.Search(len(me), func(i int) bool {
return me[i].offset > off
}) - 1
if i == -1 {
err = io.EOF
return
}
n, err := me[0].instance.ReadAt(b, off-me[0].offset)
if n == len(b) {
return n, nil
chunk := me[i]
// Go made me do this with it's bullshit named return values and := operator.
again:
n1, err := chunk.instance.ReadAt(b, off-chunk.offset)
b = b[n1:]
n += n1
// Should we check here that we're not io.EOF or nil, per ReadAt's contract? That way we know we
// don't have an error anymore for the rest of the block.
if len(b) == 0 {
// err = nil, so we don't send io.EOF on chunk boundaries?
return
}
if err == nil || err == io.EOF {
n_, err := me[1:].ReadAt(b[n:], off+int64(n))
return n + n_, err
off += int64(n1)
i++
if i >= len(me) {
if err == nil {
err = io.EOF
}
return
}
chunk = me[i]
if chunk.offset > off {
if err == nil {
err = io.ErrUnexpectedEOF
}
return
}
return n, err
goto again
}

func (s piecePerResourcePiece) getChunks(dir string) (chunks chunks) {
Expand Down

0 comments on commit 5cbffbc

Please sign in to comment.