Coverage Report

Created: 2025-08-03 06:59

/src/lzo-2.10/src/lzo1x_d.ch
Line
Count
Source (jump to first uncovered line)
1
/* lzo1x_d.ch -- implementation of the LZO1X 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
#if defined(DO_DECOMPRESS)
37
LZO_PUBLIC(int)
38
DO_DECOMPRESS  ( const lzo_bytep in , lzo_uint  in_len,
39
                       lzo_bytep out, lzo_uintp out_len,
40
                       lzo_voidp wrkmem )
41
#endif
42
1.90k
{
43
1.90k
    lzo_bytep op;
44
1.90k
    const lzo_bytep ip;
45
1.90k
    lzo_uint t;
46
#if defined(COPY_DICT)
47
    lzo_uint m_off;
48
    const lzo_bytep dict_end;
49
#else
50
1.90k
    const lzo_bytep m_pos;
51
1.90k
#endif
52
53
1.90k
    const lzo_bytep const ip_end = in + in_len;
54
1.90k
#if defined(HAVE_ANY_OP)
55
1.90k
    lzo_bytep const op_end = out + *out_len;
56
1.90k
#endif
57
#if defined(LZO1Z)
58
    lzo_uint last_m_off = 0;
59
#endif
60
61
1.90k
    LZO_UNUSED(wrkmem);
62
63
#if defined(COPY_DICT)
64
    if (dict)
65
    {
66
        if (dict_len > M4_MAX_OFFSET)
67
        {
68
            dict += dict_len - M4_MAX_OFFSET;
69
            dict_len = M4_MAX_OFFSET;
70
        }
71
        dict_end = dict + dict_len;
72
    }
73
    else
74
    {
75
        dict_len = 0;
76
        dict_end = NULL;
77
    }
78
#endif /* COPY_DICT */
79
80
1.90k
    *out_len = 0;
81
82
1.90k
    op = out;
83
1.90k
    ip = in;
84
85
1.90k
    NEED_IP(1);
86
1.90k
    if (*ip > 17)
87
1.11k
    {
88
1.11k
        t = *ip++ - 17;
89
1.11k
        if (t < 4)
90
867
            goto match_next;
91
249
        assert(t > 0); NEED_OP(t); NEED_IP(t+3);
92
8.89k
        do *op++ = *ip++; while (--t > 0);
93
204
        goto first_literal_run;
94
249
    }
95
96
793
    for (;;)
97
63.5k
    {
98
63.5k
        NEED_IP(3);
99
63.2k
        t = *ip++;
100
63.2k
        if (t >= 16)
101
37.3k
            goto match;
102
        /* a literal run */
103
25.9k
        if (t == 0)
104
12.8k
        {
105
16.2M
            while (*ip == 0)
106
16.2M
            {
107
16.2M
                t += 255;
108
16.2M
                ip++;
109
16.2M
                TEST_IV(t);
110
16.2M
                NEED_IP(1);
111
16.2M
            }
112
12.8k
            t += 15 + *ip++;
113
12.8k
        }
114
        /* copy literals */
115
25.9k
        assert(t > 0); NEED_OP(t+3); NEED_IP(t+6);
116
25.4k
#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32)
117
25.4k
        t += 3;
118
25.4k
        if (t >= 8) do
119
979k
        {
120
979k
            UA_COPY8(op,ip);
121
979k
            op += 8; ip += 8; t -= 8;
122
979k
        } while (t >= 8);
123
25.4k
        if (t >= 4)
124
15.7k
        {
125
15.7k
            UA_COPY4(op,ip);
126
15.7k
            op += 4; ip += 4; t -= 4;
127
15.7k
        }
128
25.4k
        if (t > 0)
129
17.9k
        {
130
17.9k
            *op++ = *ip++;
131
17.9k
            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
132
17.9k
        }
133
#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4)
134
#if !(LZO_OPT_UNALIGNED32)
135
        if (PTR_ALIGNED2_4(op,ip))
136
        {
137
#endif
138
        UA_COPY4(op,ip);
139
        op += 4; ip += 4;
140
        if (--t > 0)
141
        {
142
            if (t >= 4)
143
            {
144
                do {
145
                    UA_COPY4(op,ip);
146
                    op += 4; ip += 4; t -= 4;
147
                } while (t >= 4);
148
                if (t > 0) do *op++ = *ip++; while (--t > 0);
149
            }
150
            else
151
                do *op++ = *ip++; while (--t > 0);
152
        }
153
#if !(LZO_OPT_UNALIGNED32)
154
        }
155
        else
156
#endif
157
#endif
158
#if !(LZO_OPT_UNALIGNED32)
159
        {
160
            *op++ = *ip++; *op++ = *ip++; *op++ = *ip++;
161
            do *op++ = *ip++; while (--t > 0);
162
        }
163
#endif
164
165
166
25.6k
first_literal_run:
167
168
169
25.6k
        t = *ip++;
170
25.6k
        if (t >= 16)
171
12.3k
            goto match;
172
#if defined(COPY_DICT)
173
#if defined(LZO1Z)
174
        m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
175
        last_m_off = m_off;
176
#else
177
        m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2);
178
#endif
179
        NEED_OP(3);
180
        t = 3; COPY_DICT(t,m_off)
181
#else /* !COPY_DICT */
182
#if defined(LZO1Z)
183
4.05k
        t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
184
4.05k
        m_pos = op - t;
185
4.05k
        last_m_off = t;
186
#else
187
9.27k
        m_pos = op - (1 + M2_MAX_OFFSET);
188
        m_pos -= t >> 2;
189
        m_pos -= *ip++ << 2;
190
#endif
191
13.3k
        TEST_LB(m_pos); NEED_OP(3);
192
13.1k
        *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;
193
13.1k
#endif /* COPY_DICT */
194
13.1k
        goto match_done;
195
196
197
        /* handle matches */
198
103k
        for (;;) {
199
153k
match:
200
153k
            if (t >= 64)                /* a M2 match */
201
76.0k
            {
202
#if defined(COPY_DICT)
203
#if defined(LZO1X)
204
                m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3);
205
                t = (t >> 5) - 1;
206
#elif defined(LZO1Y)
207
                m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2);
208
                t = (t >> 4) - 3;
209
#elif defined(LZO1Z)
210
                m_off = t & 0x1f;
211
                if (m_off >= 0x1c)
212
                    m_off = last_m_off;
213
                else
214
                {
215
                    m_off = 1 + (m_off << 6) + (*ip++ >> 2);
216
                    last_m_off = m_off;
217
                }
218
                t = (t >> 5) - 1;
219
#endif
220
#else /* !COPY_DICT */
221
#if defined(LZO1X)
222
                m_pos = op - 1;
223
                m_pos -= (t >> 2) & 7;
224
                m_pos -= *ip++ << 3;
225
                t = (t >> 5) - 1;
226
#elif defined(LZO1Y)
227
                m_pos = op - 1;
228
                m_pos -= (t >> 2) & 3;
229
                m_pos -= *ip++ << 2;
230
                t = (t >> 4) - 3;
231
#elif defined(LZO1Z)
232
                {
233
                    lzo_uint off = t & 0x1f;
234
                    m_pos = op;
235
34.8k
                    if (off >= 0x1c)
236
17.5k
                    {
237
17.5k
                        assert(last_m_off > 0);
238
17.5k
                        m_pos -= last_m_off;
239
17.5k
                    }
240
17.2k
                    else
241
17.2k
                    {
242
17.2k
                        off = 1 + (off << 6) + (*ip++ >> 2);
243
17.2k
                        m_pos -= off;
244
17.2k
                        last_m_off = off;
245
17.2k
                    }
246
                }
247
                t = (t >> 5) - 1;
248
#endif
249
76.0k
                TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
250
75.9k
                goto copy_match;
251
75.9k
#endif /* COPY_DICT */
252
75.9k
            }
253
77.1k
            else if (t >= 32)           /* a M3 match */
254
42.3k
            {
255
42.3k
                t &= 31;
256
42.3k
                if (t == 0)
257
7.99k
                {
258
4.35M
                    while (*ip == 0)
259
4.34M
                    {
260
4.34M
                        t += 255;
261
4.34M
                        ip++;
262
4.34M
                        TEST_OV(t);
263
4.34M
                        NEED_IP(1);
264
4.34M
                    }
265
7.94k
                    t += 31 + *ip++;
266
7.94k
                    NEED_IP(2);
267
7.94k
                }
268
#if defined(COPY_DICT)
269
#if defined(LZO1Z)
270
                m_off = 1 + (ip[0] << 6) + (ip[1] >> 2);
271
                last_m_off = m_off;
272
#else
273
                m_off = 1 + (ip[0] >> 2) + (ip[1] << 6);
274
#endif
275
#else /* !COPY_DICT */
276
#if defined(LZO1Z)
277
13.0k
                {
278
13.0k
                    lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2);
279
13.0k
                    m_pos = op - off;
280
13.0k
                    last_m_off = off;
281
13.0k
                }
282
#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN)
283
29.2k
                m_pos = op - 1;
284
29.2k
                m_pos -= UA_GET_LE16(ip) >> 2;
285
#else
286
                m_pos = op - 1;
287
                m_pos -= (ip[0] >> 2) + (ip[1] << 6);
288
#endif
289
29.2k
#endif /* COPY_DICT */
290
29.2k
                ip += 2;
291
29.2k
            }
292
34.7k
            else if (t >= 16)           /* a M4 match */
293
7.40k
            {
294
#if defined(COPY_DICT)
295
                m_off = (t & 8) << 11;
296
#else /* !COPY_DICT */
297
7.40k
                m_pos = op;
298
7.40k
                m_pos -= (t & 8) << 11;
299
7.40k
#endif /* COPY_DICT */
300
7.40k
                t &= 7;
301
7.40k
                if (t == 0)
302
2.98k
                {
303
4.97M
                    while (*ip == 0)
304
4.97M
                    {
305
4.97M
                        t += 255;
306
4.97M
                        ip++;
307
4.97M
                        TEST_OV(t);
308
4.97M
                        NEED_IP(1);
309
4.97M
                    }
310
2.92k
                    t += 7 + *ip++;
311
2.92k
                    NEED_IP(2);
312
2.92k
                }
313
#if defined(COPY_DICT)
314
#if defined(LZO1Z)
315
                m_off += (ip[0] << 6) + (ip[1] >> 2);
316
#else
317
                m_off += (ip[0] >> 2) + (ip[1] << 6);
318
#endif
319
                ip += 2;
320
                if (m_off == 0)
321
                    goto eof_found;
322
                m_off += 0x4000;
323
#if defined(LZO1Z)
324
                last_m_off = m_off;
325
#endif
326
#else /* !COPY_DICT */
327
#if defined(LZO1Z)
328
2.02k
                m_pos -= (ip[0] << 6) + (ip[1] >> 2);
329
#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN)
330
5.30k
                m_pos -= UA_GET_LE16(ip) >> 2;
331
#else
332
                m_pos -= (ip[0] >> 2) + (ip[1] << 6);
333
#endif
334
5.30k
                ip += 2;
335
7.32k
                if (m_pos == op)
336
34
                    goto eof_found;
337
7.28k
                m_pos -= 0x4000;
338
#if defined(LZO1Z)
339
2.01k
                last_m_off = pd((const lzo_bytep)op, m_pos);
340
#endif
341
7.28k
#endif /* COPY_DICT */
342
7.28k
            }
343
27.3k
            else                            /* a M1 match */
344
27.3k
            {
345
#if defined(COPY_DICT)
346
#if defined(LZO1Z)
347
                m_off = 1 + (t << 6) + (*ip++ >> 2);
348
                last_m_off = m_off;
349
#else
350
                m_off = 1 + (t >> 2) + (*ip++ << 2);
351
#endif
352
                NEED_OP(2);
353
                t = 2; COPY_DICT(t,m_off)
354
#else /* !COPY_DICT */
355
#if defined(LZO1Z)
356
                t = 1 + (t << 6) + (*ip++ >> 2);
357
                m_pos = op - t;
358
                last_m_off = t;
359
#else
360
                m_pos = op - 1;
361
                m_pos -= t >> 2;
362
                m_pos -= *ip++ << 2;
363
#endif
364
27.3k
                TEST_LB(m_pos); NEED_OP(2);
365
27.2k
                *op++ = *m_pos++; *op++ = *m_pos;
366
27.2k
#endif /* COPY_DICT */
367
27.2k
                goto match_done;
368
27.2k
            }
369
370
            /* copy match */
371
#if defined(COPY_DICT)
372
373
            NEED_OP(t+3-1);
374
            t += 3-1; COPY_DICT(t,m_off)
375
376
#else /* !COPY_DICT */
377
378
49.5k
            TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
379
49.3k
#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32)
380
49.3k
            if (op - m_pos >= 8)
381
42.8k
            {
382
42.8k
                t += (3 - 1);
383
42.8k
                if (t >= 8) do
384
1.62M
                {
385
1.62M
                    UA_COPY8(op,m_pos);
386
1.62M
                    op += 8; m_pos += 8; t -= 8;
387
1.62M
                } while (t >= 8);
388
42.8k
                if (t >= 4)
389
23.2k
                {
390
23.2k
                    UA_COPY4(op,m_pos);
391
23.2k
                    op += 4; m_pos += 4; t -= 4;
392
23.2k
                }
393
42.8k
                if (t > 0)
394
37.3k
                {
395
37.3k
                    *op++ = m_pos[0];
396
37.3k
                    if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } }
397
37.3k
                }
398
42.8k
            }
399
6.50k
            else
400
#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4)
401
#if !(LZO_OPT_UNALIGNED32)
402
            if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos))
403
            {
404
                assert((op - m_pos) >= 4);  /* both pointers are aligned */
405
#else
406
            if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
407
            {
408
#endif
409
                UA_COPY4(op,m_pos);
410
                op += 4; m_pos += 4; t -= 4 - (3 - 1);
411
                do {
412
                    UA_COPY4(op,m_pos);
413
                    op += 4; m_pos += 4; t -= 4;
414
                } while (t >= 4);
415
                if (t > 0) do *op++ = *m_pos++; while (--t > 0);
416
            }
417
            else
418
#endif
419
6.50k
            {
420
82.4k
copy_match:
421
82.4k
                *op++ = *m_pos++; *op++ = *m_pos++;
422
26.3M
                do *op++ = *m_pos++; while (--t > 0);
423
82.4k
            }
424
425
49.3k
#endif /* COPY_DICT */
426
427
165k
match_done:
428
#if defined(LZO1Z)
429
            t = ip[-1] & 3;
430
#else
431
            t = ip[-2] & 3;
432
#endif
433
165k
            if (t == 0)
434
62.7k
                break;
435
436
            /* copy literals */
437
103k
match_next:
438
103k
            assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+3);
439
#if 0
440
            do *op++ = *ip++; while (--t > 0);
441
#else
442
103k
            *op++ = *ip++;
443
103k
            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
444
103k
#endif
445
103k
            t = *ip++;
446
103k
        }
447
0
    }
448
449
34
eof_found:
450
34
    *out_len = pd(op, out);
451
34
    return (ip == ip_end ? LZO_E_OK :
452
34
           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
453
454
455
0
#if defined(HAVE_NEED_IP)
456
1.21k
input_overrun:
457
1.21k
    *out_len = pd(op, out);
458
1.21k
    return LZO_E_INPUT_OVERRUN;
459
0
#endif
460
461
0
#if defined(HAVE_NEED_OP)
462
148
output_overrun:
463
148
    *out_len = pd(op, out);
464
148
    return LZO_E_OUTPUT_OVERRUN;
465
0
#endif
466
467
0
#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
468
512
lookbehind_overrun:
469
512
    *out_len = pd(op, out);
470
512
    return LZO_E_LOOKBEHIND_OVERRUN;
471
793
#endif
472
793
}
lzo1x_decompress_safe
Line
Count
Source
42
606
{
43
606
    lzo_bytep op;
44
606
    const lzo_bytep ip;
45
606
    lzo_uint t;
46
#if defined(COPY_DICT)
47
    lzo_uint m_off;
48
    const lzo_bytep dict_end;
49
#else
50
606
    const lzo_bytep m_pos;
51
606
#endif
52
53
606
    const lzo_bytep const ip_end = in + in_len;
54
606
#if defined(HAVE_ANY_OP)
55
606
    lzo_bytep const op_end = out + *out_len;
56
606
#endif
57
#if defined(LZO1Z)
58
    lzo_uint last_m_off = 0;
59
#endif
60
61
606
    LZO_UNUSED(wrkmem);
62
63
#if defined(COPY_DICT)
64
    if (dict)
65
    {
66
        if (dict_len > M4_MAX_OFFSET)
67
        {
68
            dict += dict_len - M4_MAX_OFFSET;
69
            dict_len = M4_MAX_OFFSET;
70
        }
71
        dict_end = dict + dict_len;
72
    }
73
    else
74
    {
75
        dict_len = 0;
76
        dict_end = NULL;
77
    }
78
#endif /* COPY_DICT */
79
80
606
    *out_len = 0;
81
82
606
    op = out;
83
606
    ip = in;
84
85
606
    NEED_IP(1);
86
606
    if (*ip > 17)
87
353
    {
88
353
        t = *ip++ - 17;
89
353
        if (t < 4)
90
278
            goto match_next;
91
75
        assert(t > 0); NEED_OP(t); NEED_IP(t+3);
92
2.28k
        do *op++ = *ip++; while (--t > 0);
93
60
        goto first_literal_run;
94
75
    }
95
96
253
    for (;;)
97
11.4k
    {
98
11.4k
        NEED_IP(3);
99
11.3k
        t = *ip++;
100
11.3k
        if (t >= 16)
101
6.74k
            goto match;
102
        /* a literal run */
103
4.63k
        if (t == 0)
104
2.21k
        {
105
3.67M
            while (*ip == 0)
106
3.67M
            {
107
3.67M
                t += 255;
108
3.67M
                ip++;
109
3.67M
                TEST_IV(t);
110
3.67M
                NEED_IP(1);
111
3.67M
            }
112
2.19k
            t += 15 + *ip++;
113
2.19k
        }
114
        /* copy literals */
115
4.61k
        assert(t > 0); NEED_OP(t+3); NEED_IP(t+6);
116
4.46k
#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32)
117
4.46k
        t += 3;
118
4.46k
        if (t >= 8) do
119
233k
        {
120
233k
            UA_COPY8(op,ip);
121
233k
            op += 8; ip += 8; t -= 8;
122
233k
        } while (t >= 8);
123
4.46k
        if (t >= 4)
124
2.66k
        {
125
2.66k
            UA_COPY4(op,ip);
126
2.66k
            op += 4; ip += 4; t -= 4;
127
2.66k
        }
128
4.46k
        if (t > 0)
129
3.18k
        {
130
3.18k
            *op++ = *ip++;
131
3.18k
            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
132
3.18k
        }
133
#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4)
134
#if !(LZO_OPT_UNALIGNED32)
135
        if (PTR_ALIGNED2_4(op,ip))
136
        {
137
#endif
138
        UA_COPY4(op,ip);
139
        op += 4; ip += 4;
140
        if (--t > 0)
141
        {
142
            if (t >= 4)
143
            {
144
                do {
145
                    UA_COPY4(op,ip);
146
                    op += 4; ip += 4; t -= 4;
147
                } while (t >= 4);
148
                if (t > 0) do *op++ = *ip++; while (--t > 0);
149
            }
150
            else
151
                do *op++ = *ip++; while (--t > 0);
152
        }
153
#if !(LZO_OPT_UNALIGNED32)
154
        }
155
        else
156
#endif
157
#endif
158
#if !(LZO_OPT_UNALIGNED32)
159
        {
160
            *op++ = *ip++; *op++ = *ip++; *op++ = *ip++;
161
            do *op++ = *ip++; while (--t > 0);
162
        }
163
#endif
164
165
166
4.52k
first_literal_run:
167
168
169
4.52k
        t = *ip++;
170
4.52k
        if (t >= 16)
171
2.03k
            goto match;
172
#if defined(COPY_DICT)
173
#if defined(LZO1Z)
174
        m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
175
        last_m_off = m_off;
176
#else
177
        m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2);
178
#endif
179
        NEED_OP(3);
180
        t = 3; COPY_DICT(t,m_off)
181
#else /* !COPY_DICT */
182
#if defined(LZO1Z)
183
        t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
184
        m_pos = op - t;
185
        last_m_off = t;
186
#else
187
2.49k
        m_pos = op - (1 + M2_MAX_OFFSET);
188
2.49k
        m_pos -= t >> 2;
189
2.49k
        m_pos -= *ip++ << 2;
190
2.49k
#endif
191
2.49k
        TEST_LB(m_pos); NEED_OP(3);
192
2.43k
        *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;
193
2.43k
#endif /* COPY_DICT */
194
2.43k
        goto match_done;
195
196
197
        /* handle matches */
198
22.2k
        for (;;) {
199
31.0k
match:
200
31.0k
            if (t >= 64)                /* a M2 match */
201
10.3k
            {
202
#if defined(COPY_DICT)
203
#if defined(LZO1X)
204
                m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3);
205
                t = (t >> 5) - 1;
206
#elif defined(LZO1Y)
207
                m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2);
208
                t = (t >> 4) - 3;
209
#elif defined(LZO1Z)
210
                m_off = t & 0x1f;
211
                if (m_off >= 0x1c)
212
                    m_off = last_m_off;
213
                else
214
                {
215
                    m_off = 1 + (m_off << 6) + (*ip++ >> 2);
216
                    last_m_off = m_off;
217
                }
218
                t = (t >> 5) - 1;
219
#endif
220
#else /* !COPY_DICT */
221
10.3k
#if defined(LZO1X)
222
10.3k
                m_pos = op - 1;
223
10.3k
                m_pos -= (t >> 2) & 7;
224
10.3k
                m_pos -= *ip++ << 3;
225
10.3k
                t = (t >> 5) - 1;
226
#elif defined(LZO1Y)
227
                m_pos = op - 1;
228
                m_pos -= (t >> 2) & 3;
229
                m_pos -= *ip++ << 2;
230
                t = (t >> 4) - 3;
231
#elif defined(LZO1Z)
232
                {
233
                    lzo_uint off = t & 0x1f;
234
                    m_pos = op;
235
                    if (off >= 0x1c)
236
                    {
237
                        assert(last_m_off > 0);
238
                        m_pos -= last_m_off;
239
                    }
240
                    else
241
                    {
242
                        off = 1 + (off << 6) + (*ip++ >> 2);
243
                        m_pos -= off;
244
                        last_m_off = off;
245
                    }
246
                }
247
                t = (t >> 5) - 1;
248
#endif
249
10.3k
                TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
250
10.3k
                goto copy_match;
251
10.3k
#endif /* COPY_DICT */
252
10.3k
            }
253
20.7k
            else if (t >= 32)           /* a M3 match */
254
12.3k
            {
255
12.3k
                t &= 31;
256
12.3k
                if (t == 0)
257
2.50k
                {
258
1.47M
                    while (*ip == 0)
259
1.47M
                    {
260
1.47M
                        t += 255;
261
1.47M
                        ip++;
262
1.47M
                        TEST_OV(t);
263
1.47M
                        NEED_IP(1);
264
1.47M
                    }
265
2.49k
                    t += 31 + *ip++;
266
2.49k
                    NEED_IP(2);
267
2.49k
                }
268
#if defined(COPY_DICT)
269
#if defined(LZO1Z)
270
                m_off = 1 + (ip[0] << 6) + (ip[1] >> 2);
271
                last_m_off = m_off;
272
#else
273
                m_off = 1 + (ip[0] >> 2) + (ip[1] << 6);
274
#endif
275
#else /* !COPY_DICT */
276
#if defined(LZO1Z)
277
                {
278
                    lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2);
279
                    m_pos = op - off;
280
                    last_m_off = off;
281
                }
282
#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN)
283
12.3k
                m_pos = op - 1;
284
12.3k
                m_pos -= UA_GET_LE16(ip) >> 2;
285
#else
286
                m_pos = op - 1;
287
                m_pos -= (ip[0] >> 2) + (ip[1] << 6);
288
#endif
289
12.3k
#endif /* COPY_DICT */
290
12.3k
                ip += 2;
291
12.3k
            }
292
8.33k
            else if (t >= 16)           /* a M4 match */
293
1.27k
            {
294
#if defined(COPY_DICT)
295
                m_off = (t & 8) << 11;
296
#else /* !COPY_DICT */
297
1.27k
                m_pos = op;
298
1.27k
                m_pos -= (t & 8) << 11;
299
1.27k
#endif /* COPY_DICT */
300
1.27k
                t &= 7;
301
1.27k
                if (t == 0)
302
561
                {
303
1.83M
                    while (*ip == 0)
304
1.83M
                    {
305
1.83M
                        t += 255;
306
1.83M
                        ip++;
307
1.83M
                        TEST_OV(t);
308
1.83M
                        NEED_IP(1);
309
1.83M
                    }
310
541
                    t += 7 + *ip++;
311
541
                    NEED_IP(2);
312
541
                }
313
#if defined(COPY_DICT)
314
#if defined(LZO1Z)
315
                m_off += (ip[0] << 6) + (ip[1] >> 2);
316
#else
317
                m_off += (ip[0] >> 2) + (ip[1] << 6);
318
#endif
319
                ip += 2;
320
                if (m_off == 0)
321
                    goto eof_found;
322
                m_off += 0x4000;
323
#if defined(LZO1Z)
324
                last_m_off = m_off;
325
#endif
326
#else /* !COPY_DICT */
327
#if defined(LZO1Z)
328
                m_pos -= (ip[0] << 6) + (ip[1] >> 2);
329
#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN)
330
1.24k
                m_pos -= UA_GET_LE16(ip) >> 2;
331
#else
332
                m_pos -= (ip[0] >> 2) + (ip[1] << 6);
333
#endif
334
1.24k
                ip += 2;
335
1.24k
                if (m_pos == op)
336
7
                    goto eof_found;
337
1.23k
                m_pos -= 0x4000;
338
#if defined(LZO1Z)
339
                last_m_off = pd((const lzo_bytep)op, m_pos);
340
#endif
341
1.23k
#endif /* COPY_DICT */
342
1.23k
            }
343
7.05k
            else                            /* a M1 match */
344
7.05k
            {
345
#if defined(COPY_DICT)
346
#if defined(LZO1Z)
347
                m_off = 1 + (t << 6) + (*ip++ >> 2);
348
                last_m_off = m_off;
349
#else
350
                m_off = 1 + (t >> 2) + (*ip++ << 2);
351
#endif
352
                NEED_OP(2);
353
                t = 2; COPY_DICT(t,m_off)
354
#else /* !COPY_DICT */
355
#if defined(LZO1Z)
356
                t = 1 + (t << 6) + (*ip++ >> 2);
357
                m_pos = op - t;
358
                last_m_off = t;
359
#else
360
7.05k
                m_pos = op - 1;
361
7.05k
                m_pos -= t >> 2;
362
7.05k
                m_pos -= *ip++ << 2;
363
7.05k
#endif
364
7.05k
                TEST_LB(m_pos); NEED_OP(2);
365
7.04k
                *op++ = *m_pos++; *op++ = *m_pos;
366
7.04k
#endif /* COPY_DICT */
367
7.04k
                goto match_done;
368
7.04k
            }
369
370
            /* copy match */
371
#if defined(COPY_DICT)
372
373
            NEED_OP(t+3-1);
374
            t += 3-1; COPY_DICT(t,m_off)
375
376
#else /* !COPY_DICT */
377
378
13.5k
            TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
379
13.5k
#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32)
380
13.5k
            if (op - m_pos >= 8)
381
11.4k
            {
382
11.4k
                t += (3 - 1);
383
11.4k
                if (t >= 8) do
384
507k
                {
385
507k
                    UA_COPY8(op,m_pos);
386
507k
                    op += 8; m_pos += 8; t -= 8;
387
507k
                } while (t >= 8);
388
11.4k
                if (t >= 4)
389
8.51k
                {
390
8.51k
                    UA_COPY4(op,m_pos);
391
8.51k
                    op += 4; m_pos += 4; t -= 4;
392
8.51k
                }
393
11.4k
                if (t > 0)
394
10.5k
                {
395
10.5k
                    *op++ = m_pos[0];
396
10.5k
                    if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } }
397
10.5k
                }
398
11.4k
            }
399
2.05k
            else
400
#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4)
401
#if !(LZO_OPT_UNALIGNED32)
402
            if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos))
403
            {
404
                assert((op - m_pos) >= 4);  /* both pointers are aligned */
405
#else
406
            if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
407
            {
408
#endif
409
                UA_COPY4(op,m_pos);
410
                op += 4; m_pos += 4; t -= 4 - (3 - 1);
411
                do {
412
                    UA_COPY4(op,m_pos);
413
                    op += 4; m_pos += 4; t -= 4;
414
                } while (t >= 4);
415
                if (t > 0) do *op++ = *m_pos++; while (--t > 0);
416
            }
417
            else
418
#endif
419
2.05k
            {
420
12.3k
copy_match:
421
12.3k
                *op++ = *m_pos++; *op++ = *m_pos++;
422
9.11M
                do *op++ = *m_pos++; while (--t > 0);
423
12.3k
            }
424
425
13.5k
#endif /* COPY_DICT */
426
427
33.3k
match_done:
428
#if defined(LZO1Z)
429
            t = ip[-1] & 3;
430
#else
431
33.3k
            t = ip[-2] & 3;
432
33.3k
#endif
433
33.3k
            if (t == 0)
434
11.2k
                break;
435
436
            /* copy literals */
437
22.3k
match_next:
438
22.3k
            assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+3);
439
#if 0
440
            do *op++ = *ip++; while (--t > 0);
441
#else
442
22.2k
            *op++ = *ip++;
443
22.2k
            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
444
22.2k
#endif
445
22.2k
            t = *ip++;
446
22.2k
        }
447
0
    }
448
449
7
eof_found:
450
7
    *out_len = pd(op, out);
451
7
    return (ip == ip_end ? LZO_E_OK :
452
7
           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
453
454
455
0
#if defined(HAVE_NEED_IP)
456
402
input_overrun:
457
402
    *out_len = pd(op, out);
458
402
    return LZO_E_INPUT_OVERRUN;
459
0
#endif
460
461
0
#if defined(HAVE_NEED_OP)
462
46
output_overrun:
463
46
    *out_len = pd(op, out);
464
46
    return LZO_E_OUTPUT_OVERRUN;
465
0
#endif
466
467
0
#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
468
151
lookbehind_overrun:
469
151
    *out_len = pd(op, out);
470
151
    return LZO_E_LOOKBEHIND_OVERRUN;
471
253
#endif
472
253
}
lzo1y_decompress_safe
Line
Count
Source
42
639
{
43
639
    lzo_bytep op;
44
639
    const lzo_bytep ip;
45
639
    lzo_uint t;
46
#if defined(COPY_DICT)
47
    lzo_uint m_off;
48
    const lzo_bytep dict_end;
49
#else
50
639
    const lzo_bytep m_pos;
51
639
#endif
52
53
639
    const lzo_bytep const ip_end = in + in_len;
54
639
#if defined(HAVE_ANY_OP)
55
639
    lzo_bytep const op_end = out + *out_len;
56
639
#endif
57
#if defined(LZO1Z)
58
    lzo_uint last_m_off = 0;
59
#endif
60
61
639
    LZO_UNUSED(wrkmem);
62
63
#if defined(COPY_DICT)
64
    if (dict)
65
    {
66
        if (dict_len > M4_MAX_OFFSET)
67
        {
68
            dict += dict_len - M4_MAX_OFFSET;
69
            dict_len = M4_MAX_OFFSET;
70
        }
71
        dict_end = dict + dict_len;
72
    }
73
    else
74
    {
75
        dict_len = 0;
76
        dict_end = NULL;
77
    }
78
#endif /* COPY_DICT */
79
80
639
    *out_len = 0;
81
82
639
    op = out;
83
639
    ip = in;
84
85
639
    NEED_IP(1);
86
639
    if (*ip > 17)
87
359
    {
88
359
        t = *ip++ - 17;
89
359
        if (t < 4)
90
264
            goto match_next;
91
95
        assert(t > 0); NEED_OP(t); NEED_IP(t+3);
92
4.38k
        do *op++ = *ip++; while (--t > 0);
93
80
        goto first_literal_run;
94
95
    }
95
96
280
    for (;;)
97
30.7k
    {
98
30.7k
        NEED_IP(3);
99
30.7k
        t = *ip++;
100
30.7k
        if (t >= 16)
101
17.6k
            goto match;
102
        /* a literal run */
103
13.0k
        if (t == 0)
104
7.30k
        {
105
10.6M
            while (*ip == 0)
106
10.6M
            {
107
10.6M
                t += 255;
108
10.6M
                ip++;
109
10.6M
                TEST_IV(t);
110
10.6M
                NEED_IP(1);
111
10.6M
            }
112
7.27k
            t += 15 + *ip++;
113
7.27k
        }
114
        /* copy literals */
115
13.0k
        assert(t > 0); NEED_OP(t+3); NEED_IP(t+6);
116
12.8k
#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32)
117
12.8k
        t += 3;
118
12.8k
        if (t >= 8) do
119
496k
        {
120
496k
            UA_COPY8(op,ip);
121
496k
            op += 8; ip += 8; t -= 8;
122
496k
        } while (t >= 8);
123
12.8k
        if (t >= 4)
124
8.43k
        {
125
8.43k
            UA_COPY4(op,ip);
126
8.43k
            op += 4; ip += 4; t -= 4;
127
8.43k
        }
128
12.8k
        if (t > 0)
129
9.91k
        {
130
9.91k
            *op++ = *ip++;
131
9.91k
            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
132
9.91k
        }
133
#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4)
134
#if !(LZO_OPT_UNALIGNED32)
135
        if (PTR_ALIGNED2_4(op,ip))
136
        {
137
#endif
138
        UA_COPY4(op,ip);
139
        op += 4; ip += 4;
140
        if (--t > 0)
141
        {
142
            if (t >= 4)
143
            {
144
                do {
145
                    UA_COPY4(op,ip);
146
                    op += 4; ip += 4; t -= 4;
147
                } while (t >= 4);
148
                if (t > 0) do *op++ = *ip++; while (--t > 0);
149
            }
150
            else
151
                do *op++ = *ip++; while (--t > 0);
152
        }
153
#if !(LZO_OPT_UNALIGNED32)
154
        }
155
        else
156
#endif
157
#endif
158
#if !(LZO_OPT_UNALIGNED32)
159
        {
160
            *op++ = *ip++; *op++ = *ip++; *op++ = *ip++;
161
            do *op++ = *ip++; while (--t > 0);
162
        }
163
#endif
164
165
166
12.9k
first_literal_run:
167
168
169
12.9k
        t = *ip++;
170
12.9k
        if (t >= 16)
171
6.13k
            goto match;
172
#if defined(COPY_DICT)
173
#if defined(LZO1Z)
174
        m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
175
        last_m_off = m_off;
176
#else
177
        m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2);
178
#endif
179
        NEED_OP(3);
180
        t = 3; COPY_DICT(t,m_off)
181
#else /* !COPY_DICT */
182
#if defined(LZO1Z)
183
        t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
184
        m_pos = op - t;
185
        last_m_off = t;
186
#else
187
6.78k
        m_pos = op - (1 + M2_MAX_OFFSET);
188
6.78k
        m_pos -= t >> 2;
189
6.78k
        m_pos -= *ip++ << 2;
190
6.78k
#endif
191
6.78k
        TEST_LB(m_pos); NEED_OP(3);
192
6.75k
        *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;
193
6.75k
#endif /* COPY_DICT */
194
6.75k
        goto match_done;
195
196
197
        /* handle matches */
198
44.3k
        for (;;) {
199
68.1k
match:
200
68.1k
            if (t >= 64)                /* a M2 match */
201
30.8k
            {
202
#if defined(COPY_DICT)
203
#if defined(LZO1X)
204
                m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3);
205
                t = (t >> 5) - 1;
206
#elif defined(LZO1Y)
207
                m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2);
208
                t = (t >> 4) - 3;
209
#elif defined(LZO1Z)
210
                m_off = t & 0x1f;
211
                if (m_off >= 0x1c)
212
                    m_off = last_m_off;
213
                else
214
                {
215
                    m_off = 1 + (m_off << 6) + (*ip++ >> 2);
216
                    last_m_off = m_off;
217
                }
218
                t = (t >> 5) - 1;
219
#endif
220
#else /* !COPY_DICT */
221
#if defined(LZO1X)
222
                m_pos = op - 1;
223
                m_pos -= (t >> 2) & 7;
224
                m_pos -= *ip++ << 3;
225
                t = (t >> 5) - 1;
226
#elif defined(LZO1Y)
227
                m_pos = op - 1;
228
30.8k
                m_pos -= (t >> 2) & 3;
229
30.8k
                m_pos -= *ip++ << 2;
230
30.8k
                t = (t >> 4) - 3;
231
#elif defined(LZO1Z)
232
                {
233
                    lzo_uint off = t & 0x1f;
234
                    m_pos = op;
235
                    if (off >= 0x1c)
236
                    {
237
                        assert(last_m_off > 0);
238
                        m_pos -= last_m_off;
239
                    }
240
                    else
241
                    {
242
                        off = 1 + (off << 6) + (*ip++ >> 2);
243
                        m_pos -= off;
244
                        last_m_off = off;
245
                    }
246
                }
247
                t = (t >> 5) - 1;
248
#endif
249
30.8k
                TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
250
30.8k
                goto copy_match;
251
30.8k
#endif /* COPY_DICT */
252
30.8k
            }
253
37.3k
            else if (t >= 32)           /* a M3 match */
254
16.9k
            {
255
16.9k
                t &= 31;
256
16.9k
                if (t == 0)
257
4.52k
                {
258
1.16M
                    while (*ip == 0)
259
1.16M
                    {
260
1.16M
                        t += 255;
261
1.16M
                        ip++;
262
1.16M
                        TEST_OV(t);
263
1.16M
                        NEED_IP(1);
264
1.16M
                    }
265
4.50k
                    t += 31 + *ip++;
266
4.50k
                    NEED_IP(2);
267
4.50k
                }
268
#if defined(COPY_DICT)
269
#if defined(LZO1Z)
270
                m_off = 1 + (ip[0] << 6) + (ip[1] >> 2);
271
                last_m_off = m_off;
272
#else
273
                m_off = 1 + (ip[0] >> 2) + (ip[1] << 6);
274
#endif
275
#else /* !COPY_DICT */
276
#if defined(LZO1Z)
277
                {
278
                    lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2);
279
                    m_pos = op - off;
280
                    last_m_off = off;
281
                }
282
#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN)
283
16.9k
                m_pos = op - 1;
284
16.9k
                m_pos -= UA_GET_LE16(ip) >> 2;
285
#else
286
                m_pos = op - 1;
287
                m_pos -= (ip[0] >> 2) + (ip[1] << 6);
288
#endif
289
16.9k
#endif /* COPY_DICT */
290
16.9k
                ip += 2;
291
16.9k
            }
292
20.3k
            else if (t >= 16)           /* a M4 match */
293
4.08k
            {
294
#if defined(COPY_DICT)
295
                m_off = (t & 8) << 11;
296
#else /* !COPY_DICT */
297
4.08k
                m_pos = op;
298
4.08k
                m_pos -= (t & 8) << 11;
299
4.08k
#endif /* COPY_DICT */
300
4.08k
                t &= 7;
301
4.08k
                if (t == 0)
302
1.23k
                {
303
1.84M
                    while (*ip == 0)
304
1.84M
                    {
305
1.84M
                        t += 255;
306
1.84M
                        ip++;
307
1.84M
                        TEST_OV(t);
308
1.84M
                        NEED_IP(1);
309
1.84M
                    }
310
1.21k
                    t += 7 + *ip++;
311
1.21k
                    NEED_IP(2);
312
1.21k
                }
313
#if defined(COPY_DICT)
314
#if defined(LZO1Z)
315
                m_off += (ip[0] << 6) + (ip[1] >> 2);
316
#else
317
                m_off += (ip[0] >> 2) + (ip[1] << 6);
318
#endif
319
                ip += 2;
320
                if (m_off == 0)
321
                    goto eof_found;
322
                m_off += 0x4000;
323
#if defined(LZO1Z)
324
                last_m_off = m_off;
325
#endif
326
#else /* !COPY_DICT */
327
#if defined(LZO1Z)
328
                m_pos -= (ip[0] << 6) + (ip[1] >> 2);
329
#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN)
330
4.05k
                m_pos -= UA_GET_LE16(ip) >> 2;
331
#else
332
                m_pos -= (ip[0] >> 2) + (ip[1] << 6);
333
#endif
334
4.05k
                ip += 2;
335
4.05k
                if (m_pos == op)
336
15
                    goto eof_found;
337
4.04k
                m_pos -= 0x4000;
338
#if defined(LZO1Z)
339
                last_m_off = pd((const lzo_bytep)op, m_pos);
340
#endif
341
4.04k
#endif /* COPY_DICT */
342
4.04k
            }
343
16.2k
            else                            /* a M1 match */
344
16.2k
            {
345
#if defined(COPY_DICT)
346
#if defined(LZO1Z)
347
                m_off = 1 + (t << 6) + (*ip++ >> 2);
348
                last_m_off = m_off;
349
#else
350
                m_off = 1 + (t >> 2) + (*ip++ << 2);
351
#endif
352
                NEED_OP(2);
353
                t = 2; COPY_DICT(t,m_off)
354
#else /* !COPY_DICT */
355
#if defined(LZO1Z)
356
                t = 1 + (t << 6) + (*ip++ >> 2);
357
                m_pos = op - t;
358
                last_m_off = t;
359
#else
360
16.2k
                m_pos = op - 1;
361
16.2k
                m_pos -= t >> 2;
362
16.2k
                m_pos -= *ip++ << 2;
363
16.2k
#endif
364
16.2k
                TEST_LB(m_pos); NEED_OP(2);
365
16.2k
                *op++ = *m_pos++; *op++ = *m_pos;
366
16.2k
#endif /* COPY_DICT */
367
16.2k
                goto match_done;
368
16.2k
            }
369
370
            /* copy match */
371
#if defined(COPY_DICT)
372
373
            NEED_OP(t+3-1);
374
            t += 3-1; COPY_DICT(t,m_off)
375
376
#else /* !COPY_DICT */
377
378
20.9k
            TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
379
20.8k
#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32)
380
20.8k
            if (op - m_pos >= 8)
381
17.4k
            {
382
17.4k
                t += (3 - 1);
383
17.4k
                if (t >= 8) do
384
545k
                {
385
545k
                    UA_COPY8(op,m_pos);
386
545k
                    op += 8; m_pos += 8; t -= 8;
387
545k
                } while (t >= 8);
388
17.4k
                if (t >= 4)
389
9.12k
                {
390
9.12k
                    UA_COPY4(op,m_pos);
391
9.12k
                    op += 4; m_pos += 4; t -= 4;
392
9.12k
                }
393
17.4k
                if (t > 0)
394
14.4k
                {
395
14.4k
                    *op++ = m_pos[0];
396
14.4k
                    if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } }
397
14.4k
                }
398
17.4k
            }
399
3.42k
            else
400
#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4)
401
#if !(LZO_OPT_UNALIGNED32)
402
            if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos))
403
            {
404
                assert((op - m_pos) >= 4);  /* both pointers are aligned */
405
#else
406
            if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
407
            {
408
#endif
409
                UA_COPY4(op,m_pos);
410
                op += 4; m_pos += 4; t -= 4 - (3 - 1);
411
                do {
412
                    UA_COPY4(op,m_pos);
413
                    op += 4; m_pos += 4; t -= 4;
414
                } while (t >= 4);
415
                if (t > 0) do *op++ = *m_pos++; while (--t > 0);
416
            }
417
            else
418
#endif
419
3.42k
            {
420
34.2k
copy_match:
421
34.2k
                *op++ = *m_pos++; *op++ = *m_pos++;
422
9.59M
                do *op++ = *m_pos++; while (--t > 0);
423
34.2k
            }
424
425
20.8k
#endif /* COPY_DICT */
426
427
74.7k
match_done:
428
#if defined(LZO1Z)
429
            t = ip[-1] & 3;
430
#else
431
74.7k
            t = ip[-2] & 3;
432
74.7k
#endif
433
74.7k
            if (t == 0)
434
30.5k
                break;
435
436
            /* copy literals */
437
44.4k
match_next:
438
44.4k
            assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+3);
439
#if 0
440
            do *op++ = *ip++; while (--t > 0);
441
#else
442
44.3k
            *op++ = *ip++;
443
44.3k
            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
444
44.3k
#endif
445
44.3k
            t = *ip++;
446
44.3k
        }
447
0
    }
448
449
15
eof_found:
450
15
    *out_len = pd(op, out);
451
15
    return (ip == ip_end ? LZO_E_OK :
452
15
           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
453
454
455
0
#if defined(HAVE_NEED_IP)
456
382
input_overrun:
457
382
    *out_len = pd(op, out);
458
382
    return LZO_E_INPUT_OVERRUN;
459
0
#endif
460
461
0
#if defined(HAVE_NEED_OP)
462
59
output_overrun:
463
59
    *out_len = pd(op, out);
464
59
    return LZO_E_OUTPUT_OVERRUN;
465
0
#endif
466
467
0
#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
468
183
lookbehind_overrun:
469
183
    *out_len = pd(op, out);
470
183
    return LZO_E_LOOKBEHIND_OVERRUN;
471
280
#endif
472
280
}
lzo1z_decompress_safe
Line
Count
Source
42
664
{
43
664
    lzo_bytep op;
44
664
    const lzo_bytep ip;
45
664
    lzo_uint t;
46
#if defined(COPY_DICT)
47
    lzo_uint m_off;
48
    const lzo_bytep dict_end;
49
#else
50
664
    const lzo_bytep m_pos;
51
664
#endif
52
53
664
    const lzo_bytep const ip_end = in + in_len;
54
664
#if defined(HAVE_ANY_OP)
55
664
    lzo_bytep const op_end = out + *out_len;
56
664
#endif
57
664
#if defined(LZO1Z)
58
664
    lzo_uint last_m_off = 0;
59
664
#endif
60
61
664
    LZO_UNUSED(wrkmem);
62
63
#if defined(COPY_DICT)
64
    if (dict)
65
    {
66
        if (dict_len > M4_MAX_OFFSET)
67
        {
68
            dict += dict_len - M4_MAX_OFFSET;
69
            dict_len = M4_MAX_OFFSET;
70
        }
71
        dict_end = dict + dict_len;
72
    }
73
    else
74
    {
75
        dict_len = 0;
76
        dict_end = NULL;
77
    }
78
#endif /* COPY_DICT */
79
80
664
    *out_len = 0;
81
82
664
    op = out;
83
664
    ip = in;
84
85
664
    NEED_IP(1);
86
664
    if (*ip > 17)
87
404
    {
88
404
        t = *ip++ - 17;
89
404
        if (t < 4)
90
325
            goto match_next;
91
79
        assert(t > 0); NEED_OP(t); NEED_IP(t+3);
92
2.22k
        do *op++ = *ip++; while (--t > 0);
93
64
        goto first_literal_run;
94
79
    }
95
96
260
    for (;;)
97
21.2k
    {
98
21.2k
        NEED_IP(3);
99
21.1k
        t = *ip++;
100
21.1k
        if (t >= 16)
101
12.8k
            goto match;
102
        /* a literal run */
103
8.31k
        if (t == 0)
104
3.36k
        {
105
1.87M
            while (*ip == 0)
106
1.87M
            {
107
1.87M
                t += 255;
108
1.87M
                ip++;
109
1.87M
                TEST_IV(t);
110
1.87M
                NEED_IP(1);
111
1.87M
            }
112
3.35k
            t += 15 + *ip++;
113
3.35k
        }
114
        /* copy literals */
115
8.29k
        assert(t > 0); NEED_OP(t+3); NEED_IP(t+6);
116
8.12k
#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32)
117
8.12k
        t += 3;
118
8.12k
        if (t >= 8) do
119
249k
        {
120
249k
            UA_COPY8(op,ip);
121
249k
            op += 8; ip += 8; t -= 8;
122
249k
        } while (t >= 8);
123
8.12k
        if (t >= 4)
124
4.64k
        {
125
4.64k
            UA_COPY4(op,ip);
126
4.64k
            op += 4; ip += 4; t -= 4;
127
4.64k
        }
128
8.12k
        if (t > 0)
129
4.83k
        {
130
4.83k
            *op++ = *ip++;
131
4.83k
            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
132
4.83k
        }
133
#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4)
134
#if !(LZO_OPT_UNALIGNED32)
135
        if (PTR_ALIGNED2_4(op,ip))
136
        {
137
#endif
138
        UA_COPY4(op,ip);
139
        op += 4; ip += 4;
140
        if (--t > 0)
141
        {
142
            if (t >= 4)
143
            {
144
                do {
145
                    UA_COPY4(op,ip);
146
                    op += 4; ip += 4; t -= 4;
147
                } while (t >= 4);
148
                if (t > 0) do *op++ = *ip++; while (--t > 0);
149
            }
150
            else
151
                do *op++ = *ip++; while (--t > 0);
152
        }
153
#if !(LZO_OPT_UNALIGNED32)
154
        }
155
        else
156
#endif
157
#endif
158
#if !(LZO_OPT_UNALIGNED32)
159
        {
160
            *op++ = *ip++; *op++ = *ip++; *op++ = *ip++;
161
            do *op++ = *ip++; while (--t > 0);
162
        }
163
#endif
164
165
166
8.18k
first_literal_run:
167
168
169
8.18k
        t = *ip++;
170
8.18k
        if (t >= 16)
171
4.13k
            goto match;
172
#if defined(COPY_DICT)
173
#if defined(LZO1Z)
174
        m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
175
        last_m_off = m_off;
176
#else
177
        m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2);
178
#endif
179
        NEED_OP(3);
180
        t = 3; COPY_DICT(t,m_off)
181
#else /* !COPY_DICT */
182
4.05k
#if defined(LZO1Z)
183
4.05k
        t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
184
4.05k
        m_pos = op - t;
185
4.05k
        last_m_off = t;
186
#else
187
        m_pos = op - (1 + M2_MAX_OFFSET);
188
        m_pos -= t >> 2;
189
        m_pos -= *ip++ << 2;
190
#endif
191
4.05k
        TEST_LB(m_pos); NEED_OP(3);
192
4.00k
        *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;
193
4.00k
#endif /* COPY_DICT */
194
4.00k
        goto match_done;
195
196
197
        /* handle matches */
198
36.8k
        for (;;) {
199
53.9k
match:
200
53.9k
            if (t >= 64)                /* a M2 match */
201
34.8k
            {
202
#if defined(COPY_DICT)
203
#if defined(LZO1X)
204
                m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3);
205
                t = (t >> 5) - 1;
206
#elif defined(LZO1Y)
207
                m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2);
208
                t = (t >> 4) - 3;
209
#elif defined(LZO1Z)
210
                m_off = t & 0x1f;
211
                if (m_off >= 0x1c)
212
                    m_off = last_m_off;
213
                else
214
                {
215
                    m_off = 1 + (m_off << 6) + (*ip++ >> 2);
216
                    last_m_off = m_off;
217
                }
218
                t = (t >> 5) - 1;
219
#endif
220
#else /* !COPY_DICT */
221
#if defined(LZO1X)
222
                m_pos = op - 1;
223
                m_pos -= (t >> 2) & 7;
224
                m_pos -= *ip++ << 3;
225
                t = (t >> 5) - 1;
226
#elif defined(LZO1Y)
227
                m_pos = op - 1;
228
                m_pos -= (t >> 2) & 3;
229
                m_pos -= *ip++ << 2;
230
                t = (t >> 4) - 3;
231
#elif defined(LZO1Z)
232
                {
233
34.8k
                    lzo_uint off = t & 0x1f;
234
34.8k
                    m_pos = op;
235
34.8k
                    if (off >= 0x1c)
236
17.5k
                    {
237
17.5k
                        assert(last_m_off > 0);
238
17.5k
                        m_pos -= last_m_off;
239
17.5k
                    }
240
17.2k
                    else
241
17.2k
                    {
242
17.2k
                        off = 1 + (off << 6) + (*ip++ >> 2);
243
17.2k
                        m_pos -= off;
244
17.2k
                        last_m_off = off;
245
17.2k
                    }
246
34.8k
                }
247
34.8k
                t = (t >> 5) - 1;
248
34.8k
#endif
249
34.8k
                TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
250
34.7k
                goto copy_match;
251
34.7k
#endif /* COPY_DICT */
252
34.7k
            }
253
19.0k
            else if (t >= 32)           /* a M3 match */
254
13.0k
            {
255
13.0k
                t &= 31;
256
13.0k
                if (t == 0)
257
964
                {
258
1.71M
                    while (*ip == 0)
259
1.71M
                    {
260
1.71M
                        t += 255;
261
1.71M
                        ip++;
262
1.71M
                        TEST_OV(t);
263
1.71M
                        NEED_IP(1);
264
1.71M
                    }
265
947
                    t += 31 + *ip++;
266
947
                    NEED_IP(2);
267
947
                }
268
#if defined(COPY_DICT)
269
#if defined(LZO1Z)
270
                m_off = 1 + (ip[0] << 6) + (ip[1] >> 2);
271
                last_m_off = m_off;
272
#else
273
                m_off = 1 + (ip[0] >> 2) + (ip[1] << 6);
274
#endif
275
#else /* !COPY_DICT */
276
13.0k
#if defined(LZO1Z)
277
13.0k
                {
278
13.0k
                    lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2);
279
13.0k
                    m_pos = op - off;
280
13.0k
                    last_m_off = off;
281
13.0k
                }
282
#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN)
283
                m_pos = op - 1;
284
                m_pos -= UA_GET_LE16(ip) >> 2;
285
#else
286
                m_pos = op - 1;
287
                m_pos -= (ip[0] >> 2) + (ip[1] << 6);
288
#endif
289
13.0k
#endif /* COPY_DICT */
290
13.0k
                ip += 2;
291
13.0k
            }
292
6.03k
            else if (t >= 16)           /* a M4 match */
293
2.04k
            {
294
#if defined(COPY_DICT)
295
                m_off = (t & 8) << 11;
296
#else /* !COPY_DICT */
297
2.04k
                m_pos = op;
298
2.04k
                m_pos -= (t & 8) << 11;
299
2.04k
#endif /* COPY_DICT */
300
2.04k
                t &= 7;
301
2.04k
                if (t == 0)
302
1.18k
                {
303
1.29M
                    while (*ip == 0)
304
1.29M
                    {
305
1.29M
                        t += 255;
306
1.29M
                        ip++;
307
1.29M
                        TEST_OV(t);
308
1.29M
                        NEED_IP(1);
309
1.29M
                    }
310
1.17k
                    t += 7 + *ip++;
311
1.17k
                    NEED_IP(2);
312
1.17k
                }
313
#if defined(COPY_DICT)
314
#if defined(LZO1Z)
315
                m_off += (ip[0] << 6) + (ip[1] >> 2);
316
#else
317
                m_off += (ip[0] >> 2) + (ip[1] << 6);
318
#endif
319
                ip += 2;
320
                if (m_off == 0)
321
                    goto eof_found;
322
                m_off += 0x4000;
323
#if defined(LZO1Z)
324
                last_m_off = m_off;
325
#endif
326
#else /* !COPY_DICT */
327
2.02k
#if defined(LZO1Z)
328
2.02k
                m_pos -= (ip[0] << 6) + (ip[1] >> 2);
329
#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN)
330
                m_pos -= UA_GET_LE16(ip) >> 2;
331
#else
332
                m_pos -= (ip[0] >> 2) + (ip[1] << 6);
333
#endif
334
2.02k
                ip += 2;
335
2.02k
                if (m_pos == op)
336
12
                    goto eof_found;
337
2.01k
                m_pos -= 0x4000;
338
2.01k
#if defined(LZO1Z)
339
2.01k
                last_m_off = pd((const lzo_bytep)op, m_pos);
340
2.01k
#endif
341
2.01k
#endif /* COPY_DICT */
342
2.01k
            }
343
3.98k
            else                            /* a M1 match */
344
3.98k
            {
345
#if defined(COPY_DICT)
346
#if defined(LZO1Z)
347
                m_off = 1 + (t << 6) + (*ip++ >> 2);
348
                last_m_off = m_off;
349
#else
350
                m_off = 1 + (t >> 2) + (*ip++ << 2);
351
#endif
352
                NEED_OP(2);
353
                t = 2; COPY_DICT(t,m_off)
354
#else /* !COPY_DICT */
355
3.98k
#if defined(LZO1Z)
356
3.98k
                t = 1 + (t << 6) + (*ip++ >> 2);
357
3.98k
                m_pos = op - t;
358
3.98k
                last_m_off = t;
359
#else
360
                m_pos = op - 1;
361
                m_pos -= t >> 2;
362
                m_pos -= *ip++ << 2;
363
#endif
364
3.98k
                TEST_LB(m_pos); NEED_OP(2);
365
3.97k
                *op++ = *m_pos++; *op++ = *m_pos;
366
3.97k
#endif /* COPY_DICT */
367
3.97k
                goto match_done;
368
3.97k
            }
369
370
            /* copy match */
371
#if defined(COPY_DICT)
372
373
            NEED_OP(t+3-1);
374
            t += 3-1; COPY_DICT(t,m_off)
375
376
#else /* !COPY_DICT */
377
378
15.0k
            TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
379
14.9k
#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32)
380
14.9k
            if (op - m_pos >= 8)
381
13.8k
            {
382
13.8k
                t += (3 - 1);
383
13.8k
                if (t >= 8) do
384
575k
                {
385
575k
                    UA_COPY8(op,m_pos);
386
575k
                    op += 8; m_pos += 8; t -= 8;
387
575k
                } while (t >= 8);
388
13.8k
                if (t >= 4)
389
5.59k
                {
390
5.59k
                    UA_COPY4(op,m_pos);
391
5.59k
                    op += 4; m_pos += 4; t -= 4;
392
5.59k
                }
393
13.8k
                if (t > 0)
394
12.4k
                {
395
12.4k
                    *op++ = m_pos[0];
396
12.4k
                    if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } }
397
12.4k
                }
398
13.8k
            }
399
1.03k
            else
400
#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4)
401
#if !(LZO_OPT_UNALIGNED32)
402
            if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos))
403
            {
404
                assert((op - m_pos) >= 4);  /* both pointers are aligned */
405
#else
406
            if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
407
            {
408
#endif
409
                UA_COPY4(op,m_pos);
410
                op += 4; m_pos += 4; t -= 4 - (3 - 1);
411
                do {
412
                    UA_COPY4(op,m_pos);
413
                    op += 4; m_pos += 4; t -= 4;
414
                } while (t >= 4);
415
                if (t > 0) do *op++ = *m_pos++; while (--t > 0);
416
            }
417
            else
418
#endif
419
1.03k
            {
420
35.8k
copy_match:
421
35.8k
                *op++ = *m_pos++; *op++ = *m_pos++;
422
7.66M
                do *op++ = *m_pos++; while (--t > 0);
423
35.8k
            }
424
425
14.9k
#endif /* COPY_DICT */
426
427
57.6k
match_done:
428
57.6k
#if defined(LZO1Z)
429
57.6k
            t = ip[-1] & 3;
430
#else
431
            t = ip[-2] & 3;
432
#endif
433
57.6k
            if (t == 0)
434
21.0k
                break;
435
436
            /* copy literals */
437
37.0k
match_next:
438
37.0k
            assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+3);
439
#if 0
440
            do *op++ = *ip++; while (--t > 0);
441
#else
442
36.8k
            *op++ = *ip++;
443
36.8k
            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
444
36.8k
#endif
445
36.8k
            t = *ip++;
446
36.8k
        }
447
0
    }
448
449
12
eof_found:
450
12
    *out_len = pd(op, out);
451
12
    return (ip == ip_end ? LZO_E_OK :
452
12
           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
453
454
455
0
#if defined(HAVE_NEED_IP)
456
431
input_overrun:
457
431
    *out_len = pd(op, out);
458
431
    return LZO_E_INPUT_OVERRUN;
459
0
#endif
460
461
0
#if defined(HAVE_NEED_OP)
462
43
output_overrun:
463
43
    *out_len = pd(op, out);
464
43
    return LZO_E_OUTPUT_OVERRUN;
465
0
#endif
466
467
0
#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
468
178
lookbehind_overrun:
469
178
    *out_len = pd(op, out);
470
178
    return LZO_E_LOOKBEHIND_OVERRUN;
471
260
#endif
472
260
}
473
474
475
/* vim:set ts=4 sw=4 et: */