Coverage Report

Created: 2025-08-26 06:41

/src/lzo-2.10/src/lzo1f_d.ch
Line
Count
Source (jump to first uncovered line)
1
/* lzo1f_d.ch -- implementation of the LZO1F decompression algorithm
2
3
   This file is part of the LZO real-time data compression library.
4
5
   Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer
6
   All Rights Reserved.
7
8
   The LZO library is free software; you can redistribute it and/or
9
   modify it under the terms of the GNU General Public License as
10
   published by the Free Software Foundation; either version 2 of
11
   the License, or (at your option) any later version.
12
13
   The LZO library is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
18
   You should have received a copy of the GNU General Public License
19
   along with the LZO library; see the file COPYING.
20
   If not, write to the Free Software Foundation, Inc.,
21
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22
23
   Markus F.X.J. Oberhumer
24
   <markus@oberhumer.com>
25
   http://www.oberhumer.com/opensource/lzo/
26
 */
27
28
29
#include "lzo1_d.ch"
30
31
32
/***********************************************************************
33
// decompress a block of data.
34
************************************************************************/
35
36
LZO_PUBLIC(int)
37
DO_DECOMPRESS  ( const lzo_bytep in , lzo_uint  in_len,
38
                       lzo_bytep out, lzo_uintp out_len,
39
                       lzo_voidp wrkmem )
40
1.53k
{
41
1.53k
    lzo_bytep op;
42
1.53k
    const lzo_bytep ip;
43
1.53k
    lzo_uint t;
44
1.53k
    const lzo_bytep m_pos;
45
46
1.53k
    const lzo_bytep const ip_end = in + in_len;
47
#if defined(HAVE_ANY_OP)
48
407
    lzo_bytep const op_end = out + *out_len;
49
#endif
50
51
1.53k
    LZO_UNUSED(wrkmem);
52
53
1.53k
    *out_len = 0;
54
55
1.53k
    op = out;
56
1.53k
    ip = in;
57
58
311k
    while (TEST_IP_AND_TEST_OP)
59
328k
    {
60
328k
        t = *ip++;
61
328k
        if (t > 31)
62
245k
            goto match;
63
64
        /* a literal run */
65
82.6k
        if (t == 0)
66
11.9k
        {
67
11.9k
            NEED_IP(1);
68
1.81M
            while (*ip == 0)
69
1.80M
            {
70
1.80M
                t += 255;
71
1.80M
                ip++;
72
1.80M
                TEST_IV(t);
73
1.80M
                NEED_IP(1);
74
1.77M
            }
75
625
            t += 31 + *ip++;
76
625
        }
77
        /* copy literals */
78
82.6k
        assert(t > 0); NEED_OP(t); NEED_IP(t+1);
79
4.90k
#if (LZO_OPT_UNALIGNED32)
80
82.5k
        if (t >= 4)
81
80.9k
        {
82
2.47M
            do {
83
2.47M
                UA_COPY4(op, ip);
84
2.47M
                op += 4; ip += 4; t -= 4;
85
2.47M
            } while (t >= 4);
86
96.1k
            if (t > 0) do *op++ = *ip++; while (--t > 0);
87
80.9k
        }
88
1.60k
        else
89
1.60k
#endif
90
3.03k
        do *op++ = *ip++; while (--t > 0);
91
92
4.90k
        t = *ip++;
93
94
199k
        while (TEST_IP_AND_TEST_OP)
95
241k
        {
96
            /* handle matches */
97
241k
            if (t < 32)
98
12.4k
            {
99
12.4k
                m_pos = op - 1 - 0x800;
100
12.4k
                m_pos -= (t >> 2) & 7;
101
12.4k
                m_pos -= *ip++ << 3;
102
12.4k
                TEST_LB(m_pos); NEED_OP(3);
103
7.82k
                *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos++;
104
7.82k
            }
105
228k
            else
106
228k
            {
107
474k
match:
108
474k
                if (t < M3_MARKER)
109
283k
                {
110
283k
                    m_pos = op - 1;
111
283k
                    m_pos -= (t >> 2) & 7;
112
283k
                    m_pos -= *ip++ << 3;
113
283k
                    t >>= 5;
114
283k
                    TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
115
38.1k
                    goto copy_match;
116
38.1k
                }
117
191k
                else
118
191k
                {
119
191k
                    t &= 31;
120
191k
                    if (t == 0)
121
36.6k
                    {
122
36.6k
                        NEED_IP(1);
123
1.78M
                        while (*ip == 0)
124
1.74M
                        {
125
1.74M
                            t += 255;
126
1.74M
                            ip++;
127
1.74M
                            TEST_OV(t);
128
1.74M
                            NEED_IP(1);
129
1.70M
                        }
130
1.75k
                        t += 31 + *ip++;
131
1.75k
                    }
132
190k
                    NEED_IP(2);
133
7.01k
                    m_pos = op;
134
7.01k
#if (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN)
135
190k
                    m_pos -= UA_GET_LE16(ip) >> 2;
136
7.01k
                    ip += 2;
137
#else
138
                    m_pos -= *ip++ >> 2;
139
                    m_pos -= *ip++ << 6;
140
#endif
141
190k
                    if (m_pos == op)
142
1.14k
                        goto eof_found;
143
7.01k
                }
144
145
                /* copy match */
146
189k
                TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
147
6.95k
#if (LZO_OPT_UNALIGNED32)
148
189k
                if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
149
96.1k
                {
150
96.1k
                    UA_COPY4(op, m_pos);
151
96.1k
                    op += 4; m_pos += 4; t -= 4 - (3 - 1);
152
3.80M
                    do {
153
3.80M
                        UA_COPY4(op, m_pos);
154
3.80M
                        op += 4; m_pos += 4; t -= 4;
155
3.80M
                    } while (t >= 4);
156
124k
                    if (t > 0) do *op++ = *m_pos++; while (--t > 0);
157
96.1k
                }
158
93.6k
                else
159
93.6k
#endif
160
93.6k
                {
161
376k
copy_match:
162
376k
                *op++ = *m_pos++; *op++ = *m_pos++;
163
8.94M
                do *op++ = *m_pos++; while (--t > 0);
164
376k
                }
165
6.95k
            }
166
485k
            t = ip[-2] & 3;
167
485k
            if (t == 0)
168
326k
                break;
169
170
            /* copy literals */
171
158k
            assert(t > 0); NEED_OP(t); NEED_IP(t+1);
172
280k
            do *op++ = *ip++; while (--t > 0);
173
36.4k
            t = *ip++;
174
36.4k
        }
175
4.90k
    }
176
177
#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
178
    /* no EOF code was found */
179
38
    *out_len = pd(op, out);
180
38
    return LZO_E_EOF_NOT_FOUND;
181
0
#endif
182
183
1.14k
eof_found:
184
1.14k
    assert(t == 1);
185
1.14k
    *out_len = pd(op, out);
186
1.14k
    return (ip == ip_end ? LZO_E_OK :
187
1.14k
           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
188
189
190
#if defined(HAVE_NEED_IP)
191
222
input_overrun:
192
222
    *out_len = pd(op, out);
193
222
    return LZO_E_INPUT_OVERRUN;
194
0
#endif
195
196
#if defined(HAVE_NEED_OP)
197
29
output_overrun:
198
29
    *out_len = pd(op, out);
199
29
    return LZO_E_OUTPUT_OVERRUN;
200
0
#endif
201
202
#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
203
100
lookbehind_overrun:
204
100
    *out_len = pd(op, out);
205
100
    return LZO_E_LOOKBEHIND_OVERRUN;
206
#endif
207
1.53k
}
lzo1f_decompress
Line
Count
Source
40
1.12k
{
41
1.12k
    lzo_bytep op;
42
1.12k
    const lzo_bytep ip;
43
1.12k
    lzo_uint t;
44
1.12k
    const lzo_bytep m_pos;
45
46
1.12k
    const lzo_bytep const ip_end = in + in_len;
47
#if defined(HAVE_ANY_OP)
48
    lzo_bytep const op_end = out + *out_len;
49
#endif
50
51
1.12k
    LZO_UNUSED(wrkmem);
52
53
1.12k
    *out_len = 0;
54
55
1.12k
    op = out;
56
1.12k
    ip = in;
57
58
311k
    while (TEST_IP_AND_TEST_OP)
59
311k
    {
60
311k
        t = *ip++;
61
311k
        if (t > 31)
62
233k
            goto match;
63
64
        /* a literal run */
65
77.6k
        if (t == 0)
66
11.2k
        {
67
11.2k
            NEED_IP(1);
68
39.0k
            while (*ip == 0)
69
27.7k
            {
70
27.7k
                t += 255;
71
27.7k
                ip++;
72
27.7k
                TEST_IV(t);
73
27.7k
                NEED_IP(1);
74
27.7k
            }
75
11.2k
            t += 31 + *ip++;
76
11.2k
        }
77
        /* copy literals */
78
77.6k
        assert(t > 0); NEED_OP(t); NEED_IP(t+1);
79
77.6k
#if (LZO_OPT_UNALIGNED32)
80
77.6k
        if (t >= 4)
81
77.1k
        {
82
2.20M
            do {
83
2.20M
                UA_COPY4(op, ip);
84
2.20M
                op += 4; ip += 4; t -= 4;
85
2.20M
            } while (t >= 4);
86
91.7k
            if (t > 0) do *op++ = *ip++; while (--t > 0);
87
77.1k
        }
88
516
        else
89
516
#endif
90
891
        do *op++ = *ip++; while (--t > 0);
91
92
77.6k
        t = *ip++;
93
94
199k
        while (TEST_IP_AND_TEST_OP)
95
199k
        {
96
            /* handle matches */
97
199k
            if (t < 32)
98
4.61k
            {
99
4.61k
                m_pos = op - 1 - 0x800;
100
4.61k
                m_pos -= (t >> 2) & 7;
101
4.61k
                m_pos -= *ip++ << 3;
102
4.61k
                TEST_LB(m_pos); NEED_OP(3);
103
4.61k
                *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos++;
104
4.61k
            }
105
195k
            else
106
195k
            {
107
429k
match:
108
429k
                if (t < M3_MARKER)
109
245k
                {
110
245k
                    m_pos = op - 1;
111
245k
                    m_pos -= (t >> 2) & 7;
112
245k
                    m_pos -= *ip++ << 3;
113
245k
                    t >>= 5;
114
245k
                    TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
115
245k
                    goto copy_match;
116
245k
                }
117
183k
                else
118
183k
                {
119
183k
                    t &= 31;
120
183k
                    if (t == 0)
121
34.8k
                    {
122
34.8k
                        NEED_IP(1);
123
80.3k
                        while (*ip == 0)
124
45.4k
                        {
125
45.4k
                            t += 255;
126
45.4k
                            ip++;
127
45.4k
                            TEST_OV(t);
128
45.4k
                            NEED_IP(1);
129
45.4k
                        }
130
34.8k
                        t += 31 + *ip++;
131
34.8k
                    }
132
183k
                    NEED_IP(2);
133
183k
                    m_pos = op;
134
183k
#if (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN)
135
183k
                    m_pos -= UA_GET_LE16(ip) >> 2;
136
183k
                    ip += 2;
137
#else
138
                    m_pos -= *ip++ >> 2;
139
                    m_pos -= *ip++ << 6;
140
#endif
141
183k
                    if (m_pos == op)
142
1.12k
                        goto eof_found;
143
183k
                }
144
145
                /* copy match */
146
182k
                TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
147
182k
#if (LZO_OPT_UNALIGNED32)
148
182k
                if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
149
91.0k
                {
150
91.0k
                    UA_COPY4(op, m_pos);
151
91.0k
                    op += 4; m_pos += 4; t -= 4 - (3 - 1);
152
3.06M
                    do {
153
3.06M
                        UA_COPY4(op, m_pos);
154
3.06M
                        op += 4; m_pos += 4; t -= 4;
155
3.06M
                    } while (t >= 4);
156
117k
                    if (t > 0) do *op++ = *m_pos++; while (--t > 0);
157
91.0k
                }
158
91.7k
                else
159
91.7k
#endif
160
91.7k
                {
161
336k
copy_match:
162
336k
                *op++ = *m_pos++; *op++ = *m_pos++;
163
4.39M
                do *op++ = *m_pos++; while (--t > 0);
164
336k
                }
165
182k
            }
166
432k
            t = ip[-2] & 3;
167
432k
            if (t == 0)
168
310k
                break;
169
170
            /* copy literals */
171
122k
            assert(t > 0); NEED_OP(t); NEED_IP(t+1);
172
215k
            do *op++ = *ip++; while (--t > 0);
173
122k
            t = *ip++;
174
122k
        }
175
77.6k
    }
176
177
#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
178
    /* no EOF code was found */
179
    *out_len = pd(op, out);
180
    return LZO_E_EOF_NOT_FOUND;
181
#endif
182
183
1.12k
eof_found:
184
1.12k
    assert(t == 1);
185
1.12k
    *out_len = pd(op, out);
186
1.12k
    return (ip == ip_end ? LZO_E_OK :
187
1.12k
           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
188
189
190
#if defined(HAVE_NEED_IP)
191
input_overrun:
192
    *out_len = pd(op, out);
193
    return LZO_E_INPUT_OVERRUN;
194
#endif
195
196
#if defined(HAVE_NEED_OP)
197
output_overrun:
198
    *out_len = pd(op, out);
199
    return LZO_E_OUTPUT_OVERRUN;
200
#endif
201
202
#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
203
lookbehind_overrun:
204
    *out_len = pd(op, out);
205
    return LZO_E_LOOKBEHIND_OVERRUN;
206
#endif
207
1.12k
}
lzo1f_decompress_safe
Line
Count
Source
40
407
{
41
407
    lzo_bytep op;
42
407
    const lzo_bytep ip;
43
407
    lzo_uint t;
44
407
    const lzo_bytep m_pos;
45
46
407
    const lzo_bytep const ip_end = in + in_len;
47
407
#if defined(HAVE_ANY_OP)
48
407
    lzo_bytep const op_end = out + *out_len;
49
407
#endif
50
51
407
    LZO_UNUSED(wrkmem);
52
53
407
    *out_len = 0;
54
55
407
    op = out;
56
407
    ip = in;
57
58
407
    while (TEST_IP_AND_TEST_OP)
59
16.7k
    {
60
16.7k
        t = *ip++;
61
16.7k
        if (t > 31)
62
11.7k
            goto match;
63
64
        /* a literal run */
65
5.04k
        if (t == 0)
66
656
        {
67
656
            NEED_IP(1);
68
1.77M
            while (*ip == 0)
69
1.77M
            {
70
1.77M
                t += 255;
71
1.77M
                ip++;
72
1.77M
                TEST_IV(t);
73
1.77M
                NEED_IP(1);
74
1.77M
            }
75
625
            t += 31 + *ip++;
76
625
        }
77
        /* copy literals */
78
5.01k
        assert(t > 0); NEED_OP(t); NEED_IP(t+1);
79
4.90k
#if (LZO_OPT_UNALIGNED32)
80
4.90k
        if (t >= 4)
81
3.82k
        {
82
266k
            do {
83
266k
                UA_COPY4(op, ip);
84
266k
                op += 4; ip += 4; t -= 4;
85
266k
            } while (t >= 4);
86
4.44k
            if (t > 0) do *op++ = *ip++; while (--t > 0);
87
3.82k
        }
88
1.08k
        else
89
1.08k
#endif
90
2.14k
        do *op++ = *ip++; while (--t > 0);
91
92
4.90k
        t = *ip++;
93
94
4.90k
        while (TEST_IP_AND_TEST_OP)
95
41.3k
        {
96
            /* handle matches */
97
41.3k
            if (t < 32)
98
7.87k
            {
99
7.87k
                m_pos = op - 1 - 0x800;
100
7.87k
                m_pos -= (t >> 2) & 7;
101
7.87k
                m_pos -= *ip++ << 3;
102
7.87k
                TEST_LB(m_pos); NEED_OP(3);
103
7.82k
                *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos++;
104
7.82k
            }
105
33.4k
            else
106
33.4k
            {
107
45.2k
match:
108
45.2k
                if (t < M3_MARKER)
109
38.1k
                {
110
38.1k
                    m_pos = op - 1;
111
38.1k
                    m_pos -= (t >> 2) & 7;
112
38.1k
                    m_pos -= *ip++ << 3;
113
38.1k
                    t >>= 5;
114
38.1k
                    TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
115
38.1k
                    goto copy_match;
116
38.1k
                }
117
7.05k
                else
118
7.05k
                {
119
7.05k
                    t &= 31;
120
7.05k
                    if (t == 0)
121
1.77k
                    {
122
1.77k
                        NEED_IP(1);
123
1.70M
                        while (*ip == 0)
124
1.70M
                        {
125
1.70M
                            t += 255;
126
1.70M
                            ip++;
127
1.70M
                            TEST_OV(t);
128
1.70M
                            NEED_IP(1);
129
1.70M
                        }
130
1.75k
                        t += 31 + *ip++;
131
1.75k
                    }
132
7.03k
                    NEED_IP(2);
133
7.01k
                    m_pos = op;
134
7.01k
#if (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN)
135
7.01k
                    m_pos -= UA_GET_LE16(ip) >> 2;
136
7.01k
                    ip += 2;
137
#else
138
                    m_pos -= *ip++ >> 2;
139
                    m_pos -= *ip++ << 6;
140
#endif
141
7.01k
                    if (m_pos == op)
142
18
                        goto eof_found;
143
7.01k
                }
144
145
                /* copy match */
146
6.99k
                TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
147
6.95k
#if (LZO_OPT_UNALIGNED32)
148
6.95k
                if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
149
5.08k
                {
150
5.08k
                    UA_COPY4(op, m_pos);
151
5.08k
                    op += 4; m_pos += 4; t -= 4 - (3 - 1);
152
740k
                    do {
153
740k
                        UA_COPY4(op, m_pos);
154
740k
                        op += 4; m_pos += 4; t -= 4;
155
740k
                    } while (t >= 4);
156
6.82k
                    if (t > 0) do *op++ = *m_pos++; while (--t > 0);
157
5.08k
                }
158
1.86k
                else
159
1.86k
#endif
160
1.86k
                {
161
39.9k
copy_match:
162
39.9k
                *op++ = *m_pos++; *op++ = *m_pos++;
163
4.55M
                do *op++ = *m_pos++; while (--t > 0);
164
39.9k
                }
165
6.95k
            }
166
52.9k
            t = ip[-2] & 3;
167
52.9k
            if (t == 0)
168
16.3k
                break;
169
170
            /* copy literals */
171
36.5k
            assert(t > 0); NEED_OP(t); NEED_IP(t+1);
172
65.6k
            do *op++ = *ip++; while (--t > 0);
173
36.4k
            t = *ip++;
174
36.4k
        }
175
4.90k
    }
176
177
38
#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
178
    /* no EOF code was found */
179
38
    *out_len = pd(op, out);
180
38
    return LZO_E_EOF_NOT_FOUND;
181
0
#endif
182
183
18
eof_found:
184
18
    assert(t == 1);
185
18
    *out_len = pd(op, out);
186
18
    return (ip == ip_end ? LZO_E_OK :
187
18
           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
188
189
190
0
#if defined(HAVE_NEED_IP)
191
222
input_overrun:
192
222
    *out_len = pd(op, out);
193
222
    return LZO_E_INPUT_OVERRUN;
194
0
#endif
195
196
0
#if defined(HAVE_NEED_OP)
197
29
output_overrun:
198
29
    *out_len = pd(op, out);
199
29
    return LZO_E_OUTPUT_OVERRUN;
200
0
#endif
201
202
0
#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
203
100
lookbehind_overrun:
204
100
    *out_len = pd(op, out);
205
100
    return LZO_E_LOOKBEHIND_OVERRUN;
206
407
#endif
207
407
}
208
209
210
/* vim:set ts=4 sw=4 et: */