| .. | .. |
|---|
| 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) |
|---|