diff --git a/swarm/storage/chunker.go b/swarm/storage/chunker.go index 41c0c17c12..b4ede2dbf8 100644 --- a/swarm/storage/chunker.go +++ b/swarm/storage/chunker.go @@ -496,9 +496,14 @@ func (self *LazyChunkReader) join(b []byte, off int64, eoff int64, depth int, tr start := off / treeSize end := (eoff + treeSize - 1) / treeSize + // last non-leaf chunk can be shorter than default chunk size, let's not read it further then its end + currentBranches := int64(len(chunkData)-8) / self.hashSize + if end > currentBranches { + end = currentBranches + } + wg := &sync.WaitGroup{} defer wg.Wait() - for i := start; i < end; i++ { soff := i * treeSize roff := soff diff --git a/swarm/storage/chunker_test.go b/swarm/storage/chunker_test.go index 5d9ea26a01..5dac669407 100644 --- a/swarm/storage/chunker_test.go +++ b/swarm/storage/chunker_test.go @@ -129,6 +129,21 @@ func testRandomData(usePyramid bool, hash string, n int, tester *chunkerTester) } } + // testing partial read + for i := 1; i < n; i += 10000 { + readableLength := n - i + output := make([]byte, readableLength) + r, err := reader.ReadAt(output, int64(i)) + if r != readableLength || err != io.EOF { + tester.t.Fatalf("readAt error with offset %v read: %v n = %v err = %v\n", i, r, readableLength, err) + } + if input != nil { + if !bytes.Equal(output, input[i:]) { + tester.t.Fatalf("input and output mismatch\n IN: %v\nOUT: %v\n", input[i:], output) + } + } + } + return key }