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 "libavutil/mem.h"
23 
24 #include "bytestream.h"
25 #include "snappy.h"
26 
27 enum {
32 };
33 
35 {
36  uint64_t val = 0;
37  int shift = 0;
38  int tmp;
39 
40  do {
41  tmp = bytestream2_get_byte(gb);
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 
73  bytestream2_get_buffer(gb, p, len);
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 
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 
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 
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 {
133  int pos = bytestream2_get_bytes_left(gb);
134  int64_t len = decode_len(gb);
135 
136  bytestream2_seek(gb, -pos, SEEK_END);
137 
138  return len;
139 }
140 
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 }
const char const char void * val
Definition: avisynth_c.h:863
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
static int shift(int a, int b)
Definition: sonic.c:82
Memory handling functions.
static int snappy_copy(uint8_t *start, uint8_t *p, int size, unsigned int off, int len)
Definition: snappy.c:78
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
uint8_t
ptrdiff_t size
Definition: opengl_enc.c:100
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:263
static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:154
static int snappy_copy4(GetByteContext *gb, uint8_t *start, uint8_t *p, int size, int val)
Definition: snappy.c:112
int ff_snappy_uncompress(GetByteContext *gb, uint8_t *buf, int64_t *size)
Decompress an input buffer using Snappy algorithm.
Definition: snappy.c:141
#define AVERROR_BUFFER_TOO_SMALL
Buffer too small.
Definition: error.h:51
static int snappy_literal(GetByteContext *gb, uint8_t *p, int size, int val)
Definition: snappy.c:49
static int snappy_copy1(GetByteContext *gb, uint8_t *start, uint8_t *p, int size, int val)
Definition: snappy.c:94
#define s(width, name)
Definition: cbs_vp9.c:257
Snappy decompression.
static int64_t bytestream2_get_levarint(GetByteContext *gb)
Definition: snappy.c:34
void * buf
Definition: avisynth_c.h:766
static int snappy_copy2(GetByteContext *gb, uint8_t *start, uint8_t *p, int size, int val)
Definition: snappy.c:103
int len
static int64_t decode_len(GetByteContext *gb)
Definition: snappy.c:121
static av_always_inline int bytestream2_seek(GetByteContext *g, int offset, int whence)
Definition: bytestream.h:208
void INT64 start
Definition: avisynth_c.h:766
static uint8_t tmp[11]
Definition: aes_ctr.c:26