@@ -3,11 +3,22 @@ package snappy
3
3
import (
4
4
"bytes"
5
5
"encoding/binary"
6
+ "errors"
6
7
7
8
master "github.com/golang/snappy"
8
9
)
9
10
10
- var xerialHeader = []byte {130 , 83 , 78 , 65 , 80 , 80 , 89 , 0 }
11
+ const (
12
+ sizeOffset = 16
13
+ sizeBytes = 4
14
+ )
15
+
16
+ var (
17
+ xerialHeader = []byte {130 , 83 , 78 , 65 , 80 , 80 , 89 , 0 }
18
+ // ErrMalformed is returned by the decoder when the xerial framing
19
+ // is malformed
20
+ ErrMalformed = errors .New ("malformed xerial framing" )
21
+ )
11
22
12
23
// Encode encodes data as snappy with no framing header.
13
24
func Encode (src []byte ) []byte {
@@ -17,26 +28,43 @@ func Encode(src []byte) []byte {
17
28
// Decode decodes snappy data whether it is traditional unframed
18
29
// or includes the xerial framing format.
19
30
func Decode (src []byte ) ([]byte , error ) {
31
+ var max = len (src )
32
+ if max < len (xerialHeader ) {
33
+ return nil , ErrMalformed
34
+ }
35
+
20
36
if ! bytes .Equal (src [:8 ], xerialHeader ) {
21
37
return master .Decode (nil , src )
22
38
}
23
39
40
+ if max < sizeOffset + sizeBytes {
41
+ return nil , ErrMalformed
42
+ }
43
+
24
44
var (
25
- pos = uint32 (16 )
26
- max = uint32 (len (src ))
45
+ pos = sizeOffset
27
46
dst = make ([]byte , 0 , len (src ))
28
47
chunk []byte
29
48
err error
30
49
)
31
- for pos < max {
32
- size := binary .BigEndian .Uint32 (src [pos : pos + 4 ])
33
- pos += 4
34
50
35
- chunk , err = master .Decode (chunk , src [pos :pos + size ])
51
+ for pos + sizeBytes <= max {
52
+ size := int (binary .BigEndian .Uint32 (src [pos : pos + sizeBytes ]))
53
+ pos += sizeBytes
54
+
55
+ nextPos := pos + size
56
+ // On architectures where int is 32-bytes wide size + pos could
57
+ // overflow so we need to check the low bound as well as the
58
+ // high
59
+ if nextPos < pos || nextPos > max {
60
+ return nil , ErrMalformed
61
+ }
62
+
63
+ chunk , err = master .Decode (chunk , src [pos :nextPos ])
36
64
if err != nil {
37
65
return nil , err
38
66
}
39
- pos += size
67
+ pos = nextPos
40
68
dst = append (dst , chunk ... )
41
69
}
42
70
return dst , nil
0 commit comments