@ -15,7 +15,6 @@ package chunks
import (
"bufio"
"bytes"
"encoding/binary"
"fmt"
"hash"
@ -166,6 +165,17 @@ func newCRC32() hash.Hash32 {
return crc32 . New ( castagnoliTable )
}
// Check if the CRC of data matches that stored in sum, computed when the chunk was stored.
func checkCRC32 ( data , sum [ ] byte ) error {
got := crc32 . Checksum ( data , castagnoliTable )
// This combination of shifts is the inverse of digest.Sum() in go/src/hash/crc32.
want := uint32 ( sum [ 0 ] ) << 24 + uint32 ( sum [ 1 ] ) << 16 + uint32 ( sum [ 2 ] ) << 8 + uint32 ( sum [ 3 ] )
if got != want {
return errors . Errorf ( "checksum mismatch expected:%x, actual:%x" , want , got )
}
return nil
}
// Writer implements the ChunkWriter interface for the standard
// serialization format.
type Writer struct {
@ -547,7 +557,6 @@ func (s *Reader) Size() int64 {
// Chunk returns a chunk from a given reference.
func ( s * Reader ) Chunk ( ref ChunkRef ) ( chunkenc . Chunk , error ) {
sgmIndex , chkStart := BlockChunkRef ( ref ) . Unpack ( )
chkCRC32 := newCRC32 ( )
if sgmIndex >= len ( s . bs ) {
return nil , errors . Errorf ( "segment index %d out of range" , sgmIndex )
@ -576,14 +585,10 @@ func (s *Reader) Chunk(ref ChunkRef) (chunkenc.Chunk, error) {
}
sum := sgmBytes . Range ( chkDataEnd , chkEnd )
if _ , err := chkCRC32 . Write ( sgmBytes . Range ( chkEncStart , chkDataEnd ) ) ; err != nil {
if err := checkCRC32 ( sgmBytes . Range ( chkEncStart , chkDataEnd ) , sum ) ; err != nil {
return nil , err
}
if act := chkCRC32 . Sum ( nil ) ; ! bytes . Equal ( act , sum ) {
return nil , errors . Errorf ( "checksum mismatch expected:%x, actual:%x" , sum , act )
}
chkData := sgmBytes . Range ( chkDataStart , chkDataEnd )
chkEnc := sgmBytes . Range ( chkEncStart , chkEncStart + ChunkEncodingSize ) [ 0 ]
return s . pool . Get ( chunkenc . Encoding ( chkEnc ) , chkData )