@@ -26,8 +26,11 @@ type VersionedValue struct {
2626}
2727
2828const (
29- checksumSize = 4
30- mvccSnapshotVersion = uint32 (1 )
29+ checksumSize = 4
30+ mvccSnapshotVersion = uint32 (1 )
31+ maxSnapshotKeySize = 1 << 20 // 1 MiB per key
32+ maxSnapshotVersionCount = 1 << 20 // 1M versions per key
33+ maxSnapshotValueSize = 64 << 20 // 64 MiB per value
3134)
3235
3336var mvccSnapshotMagic = [8 ]byte {'E' , 'K' , 'V' , 'M' , 'V' , 'C' , 'C' , '2' }
@@ -606,7 +609,8 @@ func writeMVCCSnapshotHeader(f *os.File) (int64, error) {
606609
607610func (s * mvccStore ) writeSnapshotBody (f * os.File ) (uint32 , error ) {
608611 hash := crc32 .NewIEEE ()
609- w := io .MultiWriter (f , hash )
612+ bw := bufio .NewWriter (f )
613+ w := io .MultiWriter (bw , hash )
610614
611615 s .mtx .RLock ()
612616 defer s .mtx .RUnlock ()
@@ -631,6 +635,9 @@ func (s *mvccStore) writeSnapshotBody(f *os.File) (uint32, error) {
631635 return 0 , err
632636 }
633637 }
638+ if err := bw .Flush (); err != nil {
639+ return 0 , errors .WithStack (err )
640+ }
634641 return hash .Sum32 (), nil
635642}
636643
@@ -788,6 +795,9 @@ func readMVCCSnapshotEntry(r io.Reader) ([]byte, []VersionedValue, bool, error)
788795 }
789796 return nil , nil , false , errors .WithStack (err )
790797 }
798+ if keyLen > maxSnapshotKeySize {
799+ return nil , nil , false , errors .Newf ("mvcc snapshot key too large: %d > %d" , keyLen , maxSnapshotKeySize )
800+ }
791801
792802 key := make ([]byte , keyLen )
793803 if _ , err := io .ReadFull (r , key ); err != nil {
@@ -798,6 +808,9 @@ func readMVCCSnapshotEntry(r io.Reader) ([]byte, []VersionedValue, bool, error)
798808 if err := binary .Read (r , binary .LittleEndian , & versionCount ); err != nil {
799809 return nil , nil , false , errors .WithStack (err )
800810 }
811+ if versionCount > maxSnapshotVersionCount {
812+ return nil , nil , false , errors .Newf ("mvcc snapshot version count too large: %d > %d" , versionCount , maxSnapshotVersionCount )
813+ }
801814 versions := make ([]VersionedValue , 0 , versionCount )
802815 for i := uint64 (0 ); i < versionCount ; i ++ {
803816 version , err := readMVCCSnapshotVersion (r )
@@ -829,6 +842,9 @@ func readMVCCSnapshotVersion(r io.Reader) (VersionedValue, error) {
829842 if err := binary .Read (r , binary .LittleEndian , & valueLen ); err != nil {
830843 return VersionedValue {}, errors .WithStack (err )
831844 }
845+ if valueLen > maxSnapshotValueSize {
846+ return VersionedValue {}, errors .Newf ("mvcc snapshot value too large: %d > %d" , valueLen , maxSnapshotValueSize )
847+ }
832848 value := make ([]byte , valueLen )
833849 if _ , err := io .ReadFull (r , value ); err != nil {
834850 return VersionedValue {}, errors .WithStack (err )
0 commit comments