github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/golang/snappy/decode_other.go (about) 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. 4 5 // +build !amd64 !gc 6 7 package snappy 8 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. 12 // 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 16 for s < len(src) { 17 switch src[s] & 0x03 { 18 case tagLiteral: 19 x := uint32(src[s] >> 2) 20 switch { 21 case x < 60: 22 s++ 23 case x == 60: 24 s += 2 25 if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. 26 return decodeErrCodeCorrupt 27 } 28 x = uint32(src[s-1]) 29 case x == 61: 30 s += 3 31 if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. 32 return decodeErrCodeCorrupt 33 } 34 x = uint32(src[s-2]) | uint32(src[s-1])<<8 35 case x == 62: 36 s += 4 37 if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. 38 return decodeErrCodeCorrupt 39 } 40 x = uint32(src[s-3]) | uint32(src[s-2])<<8 | uint32(src[s-1])<<16 41 case x == 63: 42 s += 5 43 if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. 44 return decodeErrCodeCorrupt 45 } 46 x = uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24 47 } 48 length = int(x) + 1 49 if length <= 0 { 50 return decodeErrCodeUnsupportedLiteralLength 51 } 52 if length > len(dst)-d || length > len(src)-s { 53 return decodeErrCodeCorrupt 54 } 55 copy(dst[d:], src[s:s+length]) 56 d += length 57 s += length 58 continue 59 60 case tagCopy1: 61 s += 2 62 if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. 63 return decodeErrCodeCorrupt 64 } 65 length = 4 + int(src[s-2])>>2&0x7 66 offset = int(src[s-2])&0xe0<<3 | int(src[s-1]) 67 68 case tagCopy2: 69 s += 3 70 if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. 71 return decodeErrCodeCorrupt 72 } 73 length = 1 + int(src[s-3])>>2 74 offset = int(src[s-2]) | int(src[s-1])<<8 75 76 case tagCopy4: 77 return decodeErrCodeUnsupportedCopy4Tag 78 } 79 80 if offset <= 0 || d < offset || length > len(dst)-d { 81 return decodeErrCodeCorrupt 82 } 83 // Copy from an earlier sub-slice of dst to a later sub-slice. Unlike 84 // the built-in copy function, this byte-by-byte copy always runs 85 // forwards, even if the slices overlap. Conceptually, this is: 86 // 87 // d += forwardCopy(dst[d:d+length], dst[d-offset:]) 88 for end := d + length; d != end; d++ { 89 dst[d] = dst[d-offset] 90 } 91 } 92 if d != len(dst) { 93 return decodeErrCodeCorrupt 94 } 95 return 0 96 }