FFmpeg
snappy.c
Go to the documentation of this file.
1 /*
2  * Snappy decompression algorithm
3  * Copyright (c) 2015 Luca Barbato
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "bytestream.h"
23 #include "snappy.h"
24 
25 enum {
30 };
31 
33 {
34  uint64_t val = 0;
35  int shift = 0;
36  int tmp;
37 
38  do {
39  tmp = bytestream2_get_byte(gb);
40  if (shift > 31 || ((tmp & 127LL) << shift) > INT_MAX)
41  return AVERROR_INVALIDDATA;
42  val |= (tmp & 127) << shift;
43  shift += 7;
44  } while (tmp & 128);
45 
46  return val;
47 }
48 
49 static int snappy_literal(GetByteContext *gb, uint8_t *p, int size, int val)
50 {
51  unsigned int len = 1;
52 
53  switch (val) {
54  case 63:
55  len += bytestream2_get_le32(gb);
56  break;
57  case 62:
58  len += bytestream2_get_le24(gb);
59  break;
60  case 61:
61  len += bytestream2_get_le16(gb);
62  break;
63  case 60:
64  len += bytestream2_get_byte(gb);
65  break;
66  default: // val < 60
67  len += val;
68  }
69 
70  if (size < len)
71  return AVERROR_INVALIDDATA;
72 
74 
75  return len;
76 }
77 
78 static int snappy_copy(uint8_t *start, uint8_t *p, int size,
79  unsigned int off, int len)
80 {
81  uint8_t *q;
82  int i;
83  if (off > p - start || size < len)
84  return AVERROR_INVALIDDATA;
85 
86  q = p - off;
87 
88  for (i = 0; i < len; i++)
89  p[i] = q[i];
90 
91  return len;
92 }
93 
94 static int snappy_copy1(GetByteContext *gb, uint8_t *start, uint8_t *p,
95  int size, int val)
96 {
97  int len = 4 + (val & 0x7);
98  unsigned int off = bytestream2_get_byte(gb) | (val & 0x38) << 5;
99 
100  return snappy_copy(start, p, size, off, len);
101 }
102 
103 static int snappy_copy2(GetByteContext *gb, uint8_t *start, uint8_t *p,
104  int size, int val)
105 {
106  int len = 1 + val;
107  unsigned int off = bytestream2_get_le16(gb);
108 
109  return snappy_copy(start, p, size, off, len);
110 }
111 
112 static int snappy_copy4(GetByteContext *gb, uint8_t *start, uint8_t *p,
113  int size, int val)
114 {
115  int len = 1 + val;
116  unsigned int off = bytestream2_get_le32(gb);
117 
118  return snappy_copy(start, p, size, off, len);
119 }
120 
121 static int64_t decode_len(GetByteContext *gb)
122 {
123  int64_t len = bytestream2_get_levarint(gb);
124 
125  if (len < 0 || len > UINT_MAX)
126  return AVERROR_INVALIDDATA;
127 
128  return len;
129 }
130 
132 {
134  int64_t len = decode_len(gb);
135 
136  bytestream2_seek(gb, -pos, SEEK_END);
137 
138  return len;
139 }
140 
141 int ff_snappy_uncompress(GetByteContext *gb, uint8_t *buf, int64_t *size)
142 {
143  int64_t len = decode_len(gb);
144  int ret = 0;
145  uint8_t *p;
146 
147  if (len < 0)
148  return len;
149 
150  if (len > *size)
152 
153  *size = len;
154  p = buf;
155 
156  while (bytestream2_get_bytes_left(gb) > 0) {
157  uint8_t s = bytestream2_get_byte(gb);
158  int val = s >> 2;
159 
160  switch (s & 0x03) {
161  case SNAPPY_LITERAL:
162  ret = snappy_literal(gb, p, len, val);
163  break;
164  case SNAPPY_COPY_1:
165  ret = snappy_copy1(gb, buf, p, len, val);
166  break;
167  case SNAPPY_COPY_2:
168  ret = snappy_copy2(gb, buf, p, len, val);
169  break;
170  case SNAPPY_COPY_4:
171  ret = snappy_copy4(gb, buf, p, len, val);
172  break;
173  }
174 
175  if (ret < 0)
176  return ret;
177 
178  p += ret;
179  len -= ret;
180  }
181 
182  return 0;
183 }
GetByteContext
Definition: bytestream.h:33
bytestream2_seek
static av_always_inline int bytestream2_seek(GetByteContext *g, int offset, int whence)
Definition: bytestream.h:212
tmp
static uint8_t tmp[11]
Definition: aes_ctr.c:28
bytestream2_get_levarint
static int64_t bytestream2_get_levarint(GetByteContext *gb)
Definition: snappy.c:32
val
static double val(void *priv, double ch)
Definition: aeval.c:77
AVERROR_BUFFER_TOO_SMALL
#define AVERROR_BUFFER_TOO_SMALL
Buffer too small.
Definition: error.h:53
SNAPPY_COPY_4
@ SNAPPY_COPY_4
Definition: snappy.c:29
s
#define s(width, name)
Definition: cbs_vp9.c:256
snappy_copy
static int snappy_copy(uint8_t *start, uint8_t *p, int size, unsigned int off, int len)
Definition: snappy.c:78
snappy.h
decode_len
static int64_t decode_len(GetByteContext *gb)
Definition: snappy.c:121
bytestream2_get_buffer
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:267
bytestream2_get_bytes_left
static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:158
snappy_literal
static int snappy_literal(GetByteContext *gb, uint8_t *p, int size, int val)
Definition: snappy.c:49
size
int size
Definition: twinvq_data.h:10344
SNAPPY_LITERAL
@ SNAPPY_LITERAL
Definition: snappy.c:26
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
snappy_copy4
static int snappy_copy4(GetByteContext *gb, uint8_t *start, uint8_t *p, int size, int val)
Definition: snappy.c:112
SNAPPY_COPY_2
@ SNAPPY_COPY_2
Definition: snappy.c:28
len
int len
Definition: vorbis_enc_data.h:426
ret
ret
Definition: filter_design.txt:187
pos
unsigned int pos
Definition: spdifenc.c:412
SNAPPY_COPY_1
@ SNAPPY_COPY_1
Definition: snappy.c:27
snappy_copy2
static int snappy_copy2(GetByteContext *gb, uint8_t *start, uint8_t *p, int size, int val)
Definition: snappy.c:103
shift
static int shift(int a, int b)
Definition: sonic.c:88
ff_snappy_peek_uncompressed_length
int64_t ff_snappy_peek_uncompressed_length(GetByteContext *gb)
Get the uncompressed length of an input buffer compressed using the Snappy algorithm.
Definition: snappy.c:131
ff_snappy_uncompress
int ff_snappy_uncompress(GetByteContext *gb, uint8_t *buf, int64_t *size)
Decompress an input buffer using Snappy algorithm.
Definition: snappy.c:141
bytestream.h
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
snappy_copy1
static int snappy_copy1(GetByteContext *gb, uint8_t *start, uint8_t *p, int size, int val)
Definition: snappy.c:94