1 // Copyright 2016 The Snappy-Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // +build !amd64 appengine !gc noasm
9 // decode writes the decoding of src to dst. It assumes that the varint-encoded
10 // length of the decompressed bytes has already been read, and that len(dst)
11 // equals that length.
13 // It returns 0 on success or a decodeErrCodeXxx error code on failure.
14 func decode(dst, src []byte) int {
15 var d, s, offset, length int
17 switch src[s] & 0x03 {
19 x := uint32(src[s] >> 2)
25 if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line.
26 return decodeErrCodeCorrupt
31 if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line.
32 return decodeErrCodeCorrupt
34 x = uint32(src[s-2]) | uint32(src[s-1])<<8
37 if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line.
38 return decodeErrCodeCorrupt
40 x = uint32(src[s-3]) | uint32(src[s-2])<<8 | uint32(src[s-1])<<16
43 if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line.
44 return decodeErrCodeCorrupt
46 x = uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24
50 return decodeErrCodeUnsupportedLiteralLength
52 if length > len(dst)-d || length > len(src)-s {
53 return decodeErrCodeCorrupt
55 copy(dst[d:], src[s:s+length])
62 if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line.
63 return decodeErrCodeCorrupt
65 length = 4 + int(src[s-2])>>2&0x7
66 offset = int(uint32(src[s-2])&0xe0<<3 | uint32(src[s-1]))
70 if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line.
71 return decodeErrCodeCorrupt
73 length = 1 + int(src[s-3])>>2
74 offset = int(uint32(src[s-2]) | uint32(src[s-1])<<8)
78 if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line.
79 return decodeErrCodeCorrupt
81 length = 1 + int(src[s-5])>>2
82 offset = int(uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24)
85 if offset <= 0 || d < offset || length > len(dst)-d {
86 return decodeErrCodeCorrupt
88 // Copy from an earlier sub-slice of dst to a later sub-slice. Unlike
89 // the built-in copy function, this byte-by-byte copy always runs
90 // forwards, even if the slices overlap. Conceptually, this is:
92 // d += forwardCopy(dst[d:d+length], dst[d-offset:])
93 for end := d + length; d != end; d++ {
94 dst[d] = dst[d-offset]
98 return decodeErrCodeCorrupt