1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43#include "internal.h"
44#include <asm/unaligned.h>
45#include "lz4defs.h"
46
47
48
49
50
51
52static FORCE_INLINE int customized_lz4_decompress_safe_partial(
53 const void * const source,
54 void * const dest,
55 int inputSize,
56 int outputSize)
57{
58
59 const BYTE *ip = (const BYTE *) source;
60 const BYTE * const iend = ip + inputSize;
61
62 BYTE *op = (BYTE *) dest;
63 BYTE * const oend = op + outputSize;
64 BYTE *cpy;
65
66 static const unsigned int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 };
67 static const int dec64table[] = { 0, 0, 0, -1, 0, 1, 2, 3 };
68
69
70 if (unlikely(outputSize == 0))
71 return ((inputSize == 1) && (*ip == 0)) ? 0 : -1;
72
73
74 while (1) {
75 size_t length;
76 const BYTE *match;
77 size_t offset;
78
79
80 unsigned int const token = *ip++;
81
82 length = token>>ML_BITS;
83
84 if (length == RUN_MASK) {
85 unsigned int s;
86
87 do {
88 s = *ip++;
89 length += s;
90 } while ((ip < iend - RUN_MASK) & (s == 255));
91
92 if (unlikely((size_t)(op + length) < (size_t)(op))) {
93
94 goto _output_error;
95 }
96 if (unlikely((size_t)(ip + length) < (size_t)(ip))) {
97
98 goto _output_error;
99 }
100 }
101
102
103 cpy = op + length;
104 if ((cpy > oend - WILDCOPYLENGTH) ||
105 (ip + length > iend - (2 + 1 + LASTLITERALS))) {
106 if (cpy > oend) {
107 memcpy(op, ip, length = oend - op);
108 op += length;
109 break;
110 }
111
112 if (unlikely(ip + length > iend)) {
113
114
115
116
117
118 goto _output_error;
119 }
120
121 memcpy(op, ip, length);
122 ip += length;
123 op += length;
124
125 if (ip > iend - 2)
126 break;
127
128
129 } else {
130 LZ4_wildCopy(op, ip, cpy);
131 ip += length;
132 op = cpy;
133 }
134
135
136 offset = LZ4_readLE16(ip);
137 ip += 2;
138 match = op - offset;
139
140 if (unlikely(match < (const BYTE *)dest)) {
141
142 goto _output_error;
143 }
144
145
146 length = token & ML_MASK;
147 if (length == ML_MASK) {
148 unsigned int s;
149
150 do {
151 s = *ip++;
152
153 if (ip > iend - LASTLITERALS)
154 goto _output_error;
155
156 length += s;
157 } while (s == 255);
158
159 if (unlikely((size_t)(op + length) < (size_t)op)) {
160
161 goto _output_error;
162 }
163 }
164
165 length += MINMATCH;
166
167
168 cpy = op + length;
169
170 if (unlikely(cpy >= oend - WILDCOPYLENGTH)) {
171 if (cpy >= oend) {
172 while (op < oend)
173 *op++ = *match++;
174 break;
175 }
176 goto __match;
177 }
178
179
180 LZ4_write32(op, (U32)offset);
181
182 if (unlikely(offset < 8)) {
183 const int dec64 = dec64table[offset];
184
185 op[0] = match[0];
186 op[1] = match[1];
187 op[2] = match[2];
188 op[3] = match[3];
189 match += dec32table[offset];
190 memcpy(op + 4, match, 4);
191 match -= dec64;
192 } else {
193 LZ4_copy8(op, match);
194 match += 8;
195 }
196
197 op += 8;
198
199 if (unlikely(cpy > oend - 12)) {
200 BYTE * const oCopyLimit = oend - (WILDCOPYLENGTH - 1);
201
202 if (op < oCopyLimit) {
203 LZ4_wildCopy(op, match, oCopyLimit);
204 match += oCopyLimit - op;
205 op = oCopyLimit;
206 }
207__match:
208 while (op < cpy)
209 *op++ = *match++;
210 } else {
211 LZ4_copy8(op, match);
212
213 if (length > 16)
214 LZ4_wildCopy(op + 8, match + 8, cpy);
215 }
216
217 op = cpy;
218 }
219 DBG_BUGON((void *)ip - source > inputSize);
220 DBG_BUGON((void *)op - dest > outputSize);
221
222
223 return (int) ((void *)op - dest);
224
225
226_output_error:
227 return -ERANGE;
228}
229
230int z_erofs_unzip_lz4(void *in, void *out, size_t inlen, size_t outlen)
231{
232 int ret = customized_lz4_decompress_safe_partial(in,
233 out, inlen, outlen);
234
235 if (ret >= 0)
236 return ret;
237
238
239
240
241
242 errln("%s, failed to decompress, in[%p, %zu] outlen[%p, %zu]",
243 __func__, in, inlen, out, outlen);
244 WARN_ON(1);
245 print_hex_dump(KERN_DEBUG, "raw data [in]: ", DUMP_PREFIX_OFFSET,
246 16, 1, in, inlen, true);
247 print_hex_dump(KERN_DEBUG, "raw data [out]: ", DUMP_PREFIX_OFFSET,
248 16, 1, out, outlen, true);
249 return -EIO;
250}
251
252