2 * Snappy decompression algorithm
3 * Copyright (c) 2015 Luca Barbato
5 * This file is part of FFmpeg.
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.
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.
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
22 #include "bytestream.h"
32 static int64_t bytestream2_get_levarint(GetByteContext
*gb
)
39 tmp
= bytestream2_get_byte(gb
);
40 if (shift
> 31 || ((tmp
& 127LL) << shift
) > INT_MAX
)
41 return AVERROR_INVALIDDATA
;
42 val
|= (tmp
& 127) << shift
;
49 static int snappy_literal(GetByteContext
*gb
, uint8_t *p
, int size
, int val
)
55 len
+= bytestream2_get_le32(gb
);
58 len
+= bytestream2_get_le24(gb
);
61 len
+= bytestream2_get_le16(gb
);
64 len
+= bytestream2_get_byte(gb
);
71 return AVERROR_INVALIDDATA
;
73 bytestream2_get_buffer(gb
, p
, len
);
78 static int snappy_copy(uint8_t *start
, uint8_t *p
, int size
,
79 unsigned int off
, int len
)
83 if (off
> p
- start
|| size
< len
)
84 return AVERROR_INVALIDDATA
;
88 for (i
= 0; i
< len
; i
++)
94 static int snappy_copy1(GetByteContext
*gb
, uint8_t *start
, uint8_t *p
,
97 int len
= 4 + (val
& 0x7);
98 unsigned int off
= bytestream2_get_byte(gb
) | (val
& 0x38) << 5;
100 return snappy_copy(start
, p
, size
, off
, len
);
103 static int snappy_copy2(GetByteContext
*gb
, uint8_t *start
, uint8_t *p
,
107 unsigned int off
= bytestream2_get_le16(gb
);
109 return snappy_copy(start
, p
, size
, off
, len
);
112 static int snappy_copy4(GetByteContext
*gb
, uint8_t *start
, uint8_t *p
,
116 unsigned int off
= bytestream2_get_le32(gb
);
118 return snappy_copy(start
, p
, size
, off
, len
);
121 static int64_t decode_len(GetByteContext
*gb
)
123 int64_t len
= bytestream2_get_levarint(gb
);
125 if (len
< 0 || len
> UINT_MAX
)
126 return AVERROR_INVALIDDATA
;
131 int64_t ff_snappy_peek_uncompressed_length(GetByteContext
*gb
)
133 int pos
= bytestream2_get_bytes_left(gb
);
134 int64_t len
= decode_len(gb
);
136 bytestream2_seek(gb
, -pos
, SEEK_END
);
141 int ff_snappy_uncompress(GetByteContext
*gb
, uint8_t *buf
, int64_t *size
)
143 int64_t len
= decode_len(gb
);
151 return AVERROR_BUFFER_TOO_SMALL
;
156 while (bytestream2_get_bytes_left(gb
) > 0) {
157 uint8_t s
= bytestream2_get_byte(gb
);
162 ret
= snappy_literal(gb
, p
, len
, val
);
165 ret
= snappy_copy1(gb
, buf
, p
, len
, val
);
168 ret
= snappy_copy2(gb
, buf
, p
, len
, val
);
171 ret
= snappy_copy4(gb
, buf
, p
, len
, val
);