^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * LZO1X Decompressor from LZO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * The full LZO package can be found at:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * http://www.oberhumer.com/opensource/lzo/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Changed for Linux kernel use by:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Nitin Gupta <nitingupta910@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Richard Purdie <rpurdie@openedhand.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #ifndef STATIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/lzo.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "lzodefs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define HAVE_IP(x) ((size_t)(ip_end - ip) >= (size_t)(x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define HAVE_OP(x) ((size_t)(op_end - op) >= (size_t)(x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define NEED_IP(x) if (!HAVE_IP(x)) goto input_overrun
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define NEED_OP(x) if (!HAVE_OP(x)) goto output_overrun
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define TEST_LB(m_pos) if ((m_pos) < out) goto lookbehind_overrun
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /* This MAX_255_COUNT is the maximum number of times we can add 255 to a base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * count without overflowing an integer. The multiply will overflow when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * multiplying 255 by more than MAXINT/255. The sum will overflow earlier
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * depending on the base count. Since the base count is taken from a u8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * and a few bits, it is safe to assume that it will always be lower than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * or equal to 2*255, thus we can always prevent any overflow by accepting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * two less 255 steps. See Documentation/staging/lzo.rst for more information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define MAX_255_COUNT ((((size_t)~0) / 255) - 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) unsigned char *out, size_t *out_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) unsigned char *op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) const unsigned char *ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) size_t t, next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) size_t state = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) const unsigned char *m_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) const unsigned char * const ip_end = in + in_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) unsigned char * const op_end = out + *out_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) unsigned char bitstream_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) op = out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) ip = in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (unlikely(in_len < 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) goto input_overrun;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (likely(in_len >= 5) && likely(*ip == 17)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) bitstream_version = ip[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) ip += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) bitstream_version = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (*ip > 17) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) t = *ip++ - 17;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (t < 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) next = t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) goto match_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) goto copy_literal_run;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) t = *ip++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (t < 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (likely(state == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (unlikely(t == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) size_t offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) const unsigned char *ip_last = ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) while (unlikely(*ip == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) ip++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) NEED_IP(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) offset = ip - ip_last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (unlikely(offset > MAX_255_COUNT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return LZO_E_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) offset = (offset << 8) - offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) t += offset + 15 + *ip++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) t += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) copy_literal_run:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (likely(HAVE_IP(t + 15) && HAVE_OP(t + 15))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) const unsigned char *ie = ip + t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) unsigned char *oe = op + t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) COPY8(op, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) op += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) ip += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) COPY8(op, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) op += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) ip += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) } while (ip < ie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) ip = ie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) op = oe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) NEED_OP(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) NEED_IP(t + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) *op++ = *ip++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) } while (--t > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) state = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) } else if (state != 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) next = t & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) m_pos = op - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) m_pos -= t >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) m_pos -= *ip++ << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) TEST_LB(m_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) NEED_OP(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) op[0] = m_pos[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) op[1] = m_pos[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) op += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) goto match_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) next = t & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) m_pos = op - (1 + M2_MAX_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) m_pos -= t >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) m_pos -= *ip++ << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) t = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) } else if (t >= 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) next = t & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) m_pos = op - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) m_pos -= (t >> 2) & 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) m_pos -= *ip++ << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) t = (t >> 5) - 1 + (3 - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) } else if (t >= 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) t = (t & 31) + (3 - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (unlikely(t == 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) size_t offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) const unsigned char *ip_last = ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) while (unlikely(*ip == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) ip++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) NEED_IP(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) offset = ip - ip_last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (unlikely(offset > MAX_255_COUNT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return LZO_E_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) offset = (offset << 8) - offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) t += offset + 31 + *ip++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) NEED_IP(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) m_pos = op - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) next = get_unaligned_le16(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) ip += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) m_pos -= next >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) next &= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) NEED_IP(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) next = get_unaligned_le16(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (((next & 0xfffc) == 0xfffc) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) ((t & 0xf8) == 0x18) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) likely(bitstream_version)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) NEED_IP(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) t &= 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) t |= ip[2] << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) t += MIN_ZERO_RUN_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) NEED_OP(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) memset(op, 0, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) op += t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) next &= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) ip += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) goto match_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) m_pos = op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) m_pos -= (t & 8) << 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) t = (t & 7) + (3 - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (unlikely(t == 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) size_t offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) const unsigned char *ip_last = ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) while (unlikely(*ip == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) ip++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) NEED_IP(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) offset = ip - ip_last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (unlikely(offset > MAX_255_COUNT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return LZO_E_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) offset = (offset << 8) - offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) t += offset + 7 + *ip++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) NEED_IP(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) next = get_unaligned_le16(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) ip += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) m_pos -= next >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) next &= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (m_pos == op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) goto eof_found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) m_pos -= 0x4000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) TEST_LB(m_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (op - m_pos >= 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) unsigned char *oe = op + t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (likely(HAVE_OP(t + 15))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) COPY8(op, m_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) op += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) m_pos += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) COPY8(op, m_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) op += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) m_pos += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) } while (op < oe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) op = oe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (HAVE_IP(6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) state = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) COPY4(op, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) op += next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) ip += next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) NEED_OP(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) *op++ = *m_pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) } while (op < oe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) unsigned char *oe = op + t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) NEED_OP(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) op[0] = m_pos[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) op[1] = m_pos[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) op += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) m_pos += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) *op++ = *m_pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) } while (op < oe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) match_next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) state = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) t = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (likely(HAVE_IP(6) && HAVE_OP(4))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) COPY4(op, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) op += t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) ip += t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) NEED_IP(t + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) NEED_OP(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) while (t > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) *op++ = *ip++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) t--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) eof_found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) *out_len = op - out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return (t != 3 ? LZO_E_ERROR :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) ip == ip_end ? LZO_E_OK :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) input_overrun:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) *out_len = op - out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return LZO_E_INPUT_OVERRUN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) output_overrun:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) *out_len = op - out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return LZO_E_OUTPUT_OVERRUN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) lookbehind_overrun:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) *out_len = op - out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return LZO_E_LOOKBEHIND_OVERRUN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) #ifndef STATIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) EXPORT_SYMBOL_GPL(lzo1x_decompress_safe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) MODULE_DESCRIPTION("LZO1X Decompressor");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) #endif