.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * LZO1X Decompressor from LZO |
---|
3 | 4 | * |
---|
.. | .. |
---|
31 | 32 | * depending on the base count. Since the base count is taken from a u8 |
---|
32 | 33 | * and a few bits, it is safe to assume that it will always be lower than |
---|
33 | 34 | * or equal to 2*255, thus we can always prevent any overflow by accepting |
---|
34 | | - * two less 255 steps. See Documentation/lzo.txt for more information. |
---|
| 35 | + * two less 255 steps. See Documentation/staging/lzo.rst for more information. |
---|
35 | 36 | */ |
---|
36 | 37 | #define MAX_255_COUNT ((((size_t)~0) / 255) - 2) |
---|
37 | 38 | |
---|
.. | .. |
---|
46 | 47 | const unsigned char * const ip_end = in + in_len; |
---|
47 | 48 | unsigned char * const op_end = out + *out_len; |
---|
48 | 49 | |
---|
| 50 | + unsigned char bitstream_version; |
---|
| 51 | + |
---|
49 | 52 | op = out; |
---|
50 | 53 | ip = in; |
---|
51 | 54 | |
---|
52 | 55 | if (unlikely(in_len < 3)) |
---|
53 | 56 | goto input_overrun; |
---|
| 57 | + |
---|
| 58 | + if (likely(in_len >= 5) && likely(*ip == 17)) { |
---|
| 59 | + bitstream_version = ip[1]; |
---|
| 60 | + ip += 2; |
---|
| 61 | + } else { |
---|
| 62 | + bitstream_version = 0; |
---|
| 63 | + } |
---|
| 64 | + |
---|
54 | 65 | if (*ip > 17) { |
---|
55 | 66 | t = *ip++ - 17; |
---|
56 | 67 | if (t < 4) { |
---|
.. | .. |
---|
154 | 165 | m_pos -= next >> 2; |
---|
155 | 166 | next &= 3; |
---|
156 | 167 | } else { |
---|
157 | | - m_pos = op; |
---|
158 | | - m_pos -= (t & 8) << 11; |
---|
159 | | - t = (t & 7) + (3 - 1); |
---|
160 | | - if (unlikely(t == 2)) { |
---|
161 | | - size_t offset; |
---|
162 | | - const unsigned char *ip_last = ip; |
---|
163 | | - |
---|
164 | | - while (unlikely(*ip == 0)) { |
---|
165 | | - ip++; |
---|
166 | | - NEED_IP(1); |
---|
167 | | - } |
---|
168 | | - offset = ip - ip_last; |
---|
169 | | - if (unlikely(offset > MAX_255_COUNT)) |
---|
170 | | - return LZO_E_ERROR; |
---|
171 | | - |
---|
172 | | - offset = (offset << 8) - offset; |
---|
173 | | - t += offset + 7 + *ip++; |
---|
174 | | - NEED_IP(2); |
---|
175 | | - } |
---|
| 168 | + NEED_IP(2); |
---|
176 | 169 | next = get_unaligned_le16(ip); |
---|
177 | | - ip += 2; |
---|
178 | | - m_pos -= next >> 2; |
---|
179 | | - next &= 3; |
---|
180 | | - if (m_pos == op) |
---|
181 | | - goto eof_found; |
---|
182 | | - m_pos -= 0x4000; |
---|
| 170 | + if (((next & 0xfffc) == 0xfffc) && |
---|
| 171 | + ((t & 0xf8) == 0x18) && |
---|
| 172 | + likely(bitstream_version)) { |
---|
| 173 | + NEED_IP(3); |
---|
| 174 | + t &= 7; |
---|
| 175 | + t |= ip[2] << 3; |
---|
| 176 | + t += MIN_ZERO_RUN_LENGTH; |
---|
| 177 | + NEED_OP(t); |
---|
| 178 | + memset(op, 0, t); |
---|
| 179 | + op += t; |
---|
| 180 | + next &= 3; |
---|
| 181 | + ip += 3; |
---|
| 182 | + goto match_next; |
---|
| 183 | + } else { |
---|
| 184 | + m_pos = op; |
---|
| 185 | + m_pos -= (t & 8) << 11; |
---|
| 186 | + t = (t & 7) + (3 - 1); |
---|
| 187 | + if (unlikely(t == 2)) { |
---|
| 188 | + size_t offset; |
---|
| 189 | + const unsigned char *ip_last = ip; |
---|
| 190 | + |
---|
| 191 | + while (unlikely(*ip == 0)) { |
---|
| 192 | + ip++; |
---|
| 193 | + NEED_IP(1); |
---|
| 194 | + } |
---|
| 195 | + offset = ip - ip_last; |
---|
| 196 | + if (unlikely(offset > MAX_255_COUNT)) |
---|
| 197 | + return LZO_E_ERROR; |
---|
| 198 | + |
---|
| 199 | + offset = (offset << 8) - offset; |
---|
| 200 | + t += offset + 7 + *ip++; |
---|
| 201 | + NEED_IP(2); |
---|
| 202 | + next = get_unaligned_le16(ip); |
---|
| 203 | + } |
---|
| 204 | + ip += 2; |
---|
| 205 | + m_pos -= next >> 2; |
---|
| 206 | + next &= 3; |
---|
| 207 | + if (m_pos == op) |
---|
| 208 | + goto eof_found; |
---|
| 209 | + m_pos -= 0x4000; |
---|
| 210 | + } |
---|
183 | 211 | } |
---|
184 | 212 | TEST_LB(m_pos); |
---|
185 | 213 | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) |
---|