Line data Source code
1 : /* GRAPHITE2 LICENSING
2 :
3 : Copyright 2015, SIL International
4 : All rights reserved.
5 :
6 : This library is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU Lesser General Public License as published
8 : by the Free Software Foundation; either version 2.1 of License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : Lesser General Public License for more details.
15 :
16 : You should also have received a copy of the GNU Lesser General Public
17 : License along with this library in the file named "LICENSE".
18 : If not, write to the Free Software Foundation, 51 Franklin Street,
19 : Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
20 : internet at http://www.fsf.org/licenses/lgpl.html.
21 :
22 : Alternatively, the contents of this file may be used under the terms of the
23 : Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
24 : License, as published by the Free Software Foundation, either version 2
25 : of the License or (at your option) any later version.
26 : */
27 : #include <cassert>
28 :
29 : #include "inc/Decompressor.h"
30 : #include "inc/Compression.h"
31 :
32 : using namespace lz4;
33 :
34 : namespace {
35 :
36 : inline
37 0 : u32 read_literal(u8 const * &s, u8 const * const e, u32 l) {
38 0 : if (l == 15 && s != e)
39 : {
40 0 : u8 b = 0;
41 0 : do { l += b = *s++; } while(b==0xff && s != e);
42 : }
43 0 : return l;
44 : }
45 :
46 0 : bool read_sequence(u8 const * &src, u8 const * const end, u8 const * &literal, u32 & literal_len, u32 & match_len, u32 & match_dist)
47 : {
48 0 : u8 const token = *src++;
49 :
50 0 : literal_len = read_literal(src, end, token >> 4);
51 0 : literal = src;
52 0 : src += literal_len;
53 :
54 0 : if (src > end - 2 || src < literal)
55 0 : return false;
56 :
57 0 : match_dist = *src++;
58 0 : match_dist |= *src++ << 8;
59 0 : match_len = read_literal(src, end, token & 0xf);
60 :
61 0 : return src <= end-5;
62 : }
63 :
64 : }
65 :
66 0 : int lz4::decompress(void const *in, size_t in_size, void *out, size_t out_size)
67 : {
68 0 : if (out_size <= in_size || in_size < sizeof(unsigned long)+1)
69 0 : return -1;
70 :
71 0 : u8 const * src = static_cast<u8 const *>(in),
72 0 : * literal = 0,
73 0 : * const src_end = src + in_size;
74 :
75 0 : u8 * dst = static_cast<u8*>(out),
76 0 : * const dst_end = dst + out_size;
77 :
78 0 : u32 literal_len = 0,
79 0 : match_len = 0,
80 0 : match_dist = 0;
81 :
82 0 : while (read_sequence(src, src_end, literal, literal_len, match_len, match_dist))
83 : {
84 0 : if (literal_len != 0)
85 : {
86 : // Copy in literal. At this point the last full sequence must be at
87 : // least MINMATCH + 5 from the end of the output buffer.
88 0 : if (align(literal_len) > unsigned(dst_end - dst - (MINMATCH+5)) || dst_end - dst < MINMATCH + 5)
89 0 : return -1;
90 0 : dst = overrun_copy(dst, literal, literal_len);
91 : }
92 :
93 : // Copy, possibly repeating, match from earlier in the
94 : // decoded output.
95 0 : u8 const * const pcpy = dst - match_dist;
96 0 : if (pcpy < static_cast<u8*>(out)
97 0 : || pcpy >= dst
98 0 : || match_len > unsigned(dst_end - dst - (MINMATCH+5))
99 0 : || dst_end - dst < MINMATCH + 5)
100 0 : return -1;
101 0 : if (dst > pcpy+sizeof(unsigned long)
102 0 : && dst + align(match_len + MINMATCH) <= dst_end)
103 0 : dst = overrun_copy(dst, pcpy, match_len + MINMATCH);
104 : else
105 0 : dst = safe_copy(dst, pcpy, match_len + MINMATCH);
106 : }
107 :
108 0 : if (literal_len > src_end - literal
109 0 : || literal_len > dst_end - dst)
110 0 : return -1;
111 0 : dst = fast_copy(dst, literal, literal_len);
112 :
113 0 : return dst - (u8*)out;
114 : }
115 :
|