Coverage Report

Created: 2026-06-10 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/lzo-2.10/src/lzo1x_d.ch
Line
Count
Source
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.89k
{
43
1.89k
    lzo_bytep op;
44
1.89k
    const lzo_bytep ip;
45
1.89k
    lzo_uint t;
46
#if defined(COPY_DICT)
47
    lzo_uint m_off;
48
    const lzo_bytep dict_end;
49
#else
50
1.89k
    const lzo_bytep m_pos;
51
1.89k
#endif
52
53
1.89k
    const lzo_bytep const ip_end = in + in_len;
54
1.89k
#if defined(HAVE_ANY_OP)
55
1.89k
    lzo_bytep const op_end = out + *out_len;
56
1.89k
#endif
57
#if defined(LZO1Z)
58
    lzo_uint last_m_off = 0;
59
#endif
60
61
1.89k
    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.89k
    *out_len = 0;
81
82
1.89k
    op = out;
83
1.89k
    ip = in;
84
85
1.89k
    NEED_IP(1);
86
1.89k
    if (*ip > 17)
87
1.17k
    {
88
1.17k
        t = *ip++ - 17;
89
1.17k
        if (t < 4)
90
861
            goto match_next;
91
1.17k
        assert(t > 0); NEED_OP(t); NEED_IP(t+3);
92
5.88k
        do *op++ = *ip++; while (--t > 0);
93
276
        goto first_literal_run;
94
314
    }
95
96
715
    for (;;)
97
191k
    {
98
191k
        NEED_IP(3);
99
191k
        t = *ip++;
100
191k
        if (t >= 16)
101
138k
            goto match;
102
        /* a literal run */
103
52.6k
        if (t == 0)
104
30.1k
        {
105
25.6M
            while (*ip == 0)
106
25.5M
            {
107
25.5M
                t += 255;
108
25.5M
                ip++;
109
25.5M
                TEST_IV(t);
110
25.5M
                NEED_IP(1);
111
25.5M
            }
112
30.0k
            t += 15 + *ip++;
113
30.0k
        }
114
        /* copy literals */
115
52.6k
        assert(t > 0); NEED_OP(t+3); NEED_IP(t+6);
116
52.0k
#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32)
117
52.0k
        t += 3;
118
52.0k
        if (t >= 8) do
119
1.33M
        {
120
1.33M
            UA_COPY8(op,ip);
121
1.33M
            op += 8; ip += 8; t -= 8;
122
1.33M
        } while (t >= 8);
123
52.0k
        if (t >= 4)
124
27.8k
        {
125
27.8k
            UA_COPY4(op,ip);
126
27.8k
            op += 4; ip += 4; t -= 4;
127
27.8k
        }
128
52.0k
        if (t > 0)
129
40.2k
        {
130
40.2k
            *op++ = *ip++;
131
40.2k
            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
132
40.2k
        }
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
52.3k
first_literal_run:
167
168
169
52.3k
        t = *ip++;
170
52.3k
        if (t >= 16)
171
22.6k
            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
6.78k
        t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
184
6.78k
        m_pos = op - t;
185
6.78k
        last_m_off = t;
186
#else
187
22.9k
        m_pos = op - (1 + M2_MAX_OFFSET);
188
        m_pos -= t >> 2;
189
        m_pos -= *ip++ << 2;
190
#endif
191
29.7k
        TEST_LB(m_pos); NEED_OP(3);
192
29.6k
        *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;
193
29.6k
#endif /* COPY_DICT */
194
29.6k
        goto match_done;
195
196
197
        /* handle matches */
198
315k
        for (;;) {
199
477k
match:
200
477k
            if (t >= 64)                /* a M2 match */
201
245k
            {
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
85.6k
                    if (off >= 0x1c)
236
12.3k
                    {
237
12.3k
                        assert(last_m_off > 0);
238
12.3k
                        m_pos -= last_m_off;
239
12.3k
                    }
240
73.3k
                    else
241
73.3k
                    {
242
73.3k
                        off = 1 + (off << 6) + (*ip++ >> 2);
243
73.3k
                        m_pos -= off;
244
73.3k
                        last_m_off = off;
245
73.3k
                    }
246
                }
247
                t = (t >> 5) - 1;
248
#endif
249
245k
                TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
250
245k
                goto copy_match;
251
245k
#endif /* COPY_DICT */
252
245k
            }
253
231k
            else if (t >= 32)           /* a M3 match */
254
87.2k
            {
255
87.2k
                t &= 31;
256
87.2k
                if (t == 0)
257
10.1k
                {
258
19.1M
                    while (*ip == 0)
259
19.1M
                    {
260
19.1M
                        t += 255;
261
19.1M
                        ip++;
262
19.1M
                        TEST_OV(t);
263
19.1M
                        NEED_IP(1);
264
19.1M
                    }
265
10.0k
                    t += 31 + *ip++;
266
10.0k
                    NEED_IP(2);
267
10.0k
                }
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
20.2k
                {
278
20.2k
                    lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2);
279
20.2k
                    m_pos = op - off;
280
20.2k
                    last_m_off = off;
281
20.2k
                }
282
#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN)
283
66.8k
                m_pos = op - 1;
284
66.8k
                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
66.8k
#endif /* COPY_DICT */
290
66.8k
                ip += 2;
291
66.8k
            }
292
144k
            else if (t >= 16)           /* a M4 match */
293
24.9k
            {
294
#if defined(COPY_DICT)
295
                m_off = (t & 8) << 11;
296
#else /* !COPY_DICT */
297
24.9k
                m_pos = op;
298
24.9k
                m_pos -= (t & 8) << 11;
299
24.9k
#endif /* COPY_DICT */
300
24.9k
                t &= 7;
301
24.9k
                if (t == 0)
302
7.69k
                {
303
7.95M
                    while (*ip == 0)
304
7.94M
                    {
305
7.94M
                        t += 255;
306
7.94M
                        ip++;
307
7.94M
                        TEST_OV(t);
308
7.94M
                        NEED_IP(1);
309
7.94M
                    }
310
7.64k
                    t += 7 + *ip++;
311
7.64k
                    NEED_IP(2);
312
7.64k
                }
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
6.35k
                m_pos -= (ip[0] << 6) + (ip[1] >> 2);
329
#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN)
330
18.5k
                m_pos -= UA_GET_LE16(ip) >> 2;
331
#else
332
                m_pos -= (ip[0] >> 2) + (ip[1] << 6);
333
#endif
334
18.5k
                ip += 2;
335
24.8k
                if (m_pos == op)
336
46
                    goto eof_found;
337
24.8k
                m_pos -= 0x4000;
338
#if defined(LZO1Z)
339
6.33k
                last_m_off = pd((const lzo_bytep)op, m_pos);
340
#endif
341
24.8k
#endif /* COPY_DICT */
342
24.8k
            }
343
119k
            else                            /* a M1 match */
344
119k
            {
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
119k
                TEST_LB(m_pos); NEED_OP(2);
365
119k
                *op++ = *m_pos++; *op++ = *m_pos;
366
119k
#endif /* COPY_DICT */
367
119k
                goto match_done;
368
119k
            }
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
111k
            TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
379
111k
#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32)
380
111k
            if (op - m_pos >= 8)
381
102k
            {
382
102k
                t += (3 - 1);
383
102k
                if (t >= 8) do
384
2.15M
                {
385
2.15M
                    UA_COPY8(op,m_pos);
386
2.15M
                    op += 8; m_pos += 8; t -= 8;
387
2.15M
                } while (t >= 8);
388
102k
                if (t >= 4)
389
57.4k
                {
390
57.4k
                    UA_COPY4(op,m_pos);
391
57.4k
                    op += 4; m_pos += 4; t -= 4;
392
57.4k
                }
393
102k
                if (t > 0)
394
78.2k
                {
395
78.2k
                    *op++ = m_pos[0];
396
78.2k
                    if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } }
397
78.2k
                }
398
102k
            }
399
9.53k
            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
9.53k
            {
420
254k
copy_match:
421
254k
                *op++ = *m_pos++; *op++ = *m_pos++;
422
30.2M
                do *op++ = *m_pos++; while (--t > 0);
423
254k
            }
424
425
111k
#endif /* COPY_DICT */
426
427
505k
match_done:
428
#if defined(LZO1Z)
429
            t = ip[-1] & 3;
430
#else
431
            t = ip[-2] & 3;
432
#endif
433
505k
            if (t == 0)
434
190k
                break;
435
436
            /* copy literals */
437
316k
match_next:
438
316k
            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
315k
            *op++ = *ip++;
443
315k
            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
444
315k
#endif
445
315k
            t = *ip++;
446
315k
        }
447
0
    }
448
449
46
eof_found:
450
46
    *out_len = pd(op, out);
451
46
    return (ip == ip_end ? LZO_E_OK :
452
46
           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
453
454
455
0
#if defined(HAVE_NEED_IP)
456
1.17k
input_overrun:
457
1.17k
    *out_len = pd(op, out);
458
1.17k
    return LZO_E_INPUT_OVERRUN;
459
0
#endif
460
461
0
#if defined(HAVE_NEED_OP)
462
191
output_overrun:
463
191
    *out_len = pd(op, out);
464
191
    return LZO_E_OUTPUT_OVERRUN;
465
0
#endif
466
467
0
#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
468
476
lookbehind_overrun:
469
476
    *out_len = pd(op, out);
470
476
    return LZO_E_LOOKBEHIND_OVERRUN;
471
715
#endif
472
715
}
lzo1x_decompress_safe
Line
Count
Source
42
623
{
43
623
    lzo_bytep op;
44
623
    const lzo_bytep ip;
45
623
    lzo_uint t;
46
#if defined(COPY_DICT)
47
    lzo_uint m_off;
48
    const lzo_bytep dict_end;
49
#else
50
623
    const lzo_bytep m_pos;
51
623
#endif
52
53
623
    const lzo_bytep const ip_end = in + in_len;
54
623
#if defined(HAVE_ANY_OP)
55
623
    lzo_bytep const op_end = out + *out_len;
56
623
#endif
57
#if defined(LZO1Z)
58
    lzo_uint last_m_off = 0;
59
#endif
60
61
623
    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
623
    *out_len = 0;
81
82
623
    op = out;
83
623
    ip = in;
84
85
623
    NEED_IP(1);
86
623
    if (*ip > 17)
87
375
    {
88
375
        t = *ip++ - 17;
89
375
        if (t < 4)
90
277
            goto match_next;
91
375
        assert(t > 0); NEED_OP(t); NEED_IP(t+3);
92
1.67k
        do *op++ = *ip++; while (--t > 0);
93
86
        goto first_literal_run;
94
98
    }
95
96
248
    for (;;)
97
50.1k
    {
98
50.1k
        NEED_IP(3);
99
50.1k
        t = *ip++;
100
50.1k
        if (t >= 16)
101
35.6k
            goto match;
102
        /* a literal run */
103
14.4k
        if (t == 0)
104
9.20k
        {
105
4.11M
            while (*ip == 0)
106
4.10M
            {
107
4.10M
                t += 255;
108
4.10M
                ip++;
109
4.10M
                TEST_IV(t);
110
4.10M
                NEED_IP(1);
111
4.10M
            }
112
9.18k
            t += 15 + *ip++;
113
9.18k
        }
114
        /* copy literals */
115
14.4k
        assert(t > 0); NEED_OP(t+3); NEED_IP(t+6);
116
14.2k
#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32)
117
14.2k
        t += 3;
118
14.2k
        if (t >= 8) do
119
287k
        {
120
287k
            UA_COPY8(op,ip);
121
287k
            op += 8; ip += 8; t -= 8;
122
287k
        } while (t >= 8);
123
14.2k
        if (t >= 4)
124
7.07k
        {
125
7.07k
            UA_COPY4(op,ip);
126
7.07k
            op += 4; ip += 4; t -= 4;
127
7.07k
        }
128
14.2k
        if (t > 0)
129
11.7k
        {
130
11.7k
            *op++ = *ip++;
131
11.7k
            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
132
11.7k
        }
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
14.3k
first_literal_run:
167
168
169
14.3k
        t = *ip++;
170
14.3k
        if (t >= 16)
171
5.18k
            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
9.14k
        m_pos = op - (1 + M2_MAX_OFFSET);
188
9.14k
        m_pos -= t >> 2;
189
9.14k
        m_pos -= *ip++ << 2;
190
9.14k
#endif
191
9.14k
        TEST_LB(m_pos); NEED_OP(3);
192
9.10k
        *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;
193
9.10k
#endif /* COPY_DICT */
194
9.10k
        goto match_done;
195
196
197
        /* handle matches */
198
86.1k
        for (;;) {
199
127k
match:
200
127k
            if (t >= 64)                /* a M2 match */
201
61.7k
            {
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
61.7k
#if defined(LZO1X)
222
61.7k
                m_pos = op - 1;
223
61.7k
                m_pos -= (t >> 2) & 7;
224
61.7k
                m_pos -= *ip++ << 3;
225
61.7k
                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
61.7k
                TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
250
61.7k
                goto copy_match;
251
61.7k
#endif /* COPY_DICT */
252
61.7k
            }
253
65.3k
            else if (t >= 32)           /* a M3 match */
254
31.8k
            {
255
31.8k
                t &= 31;
256
31.8k
                if (t == 0)
257
3.54k
                {
258
1.31M
                    while (*ip == 0)
259
1.31M
                    {
260
1.31M
                        t += 255;
261
1.31M
                        ip++;
262
1.31M
                        TEST_OV(t);
263
1.31M
                        NEED_IP(1);
264
1.31M
                    }
265
3.52k
                    t += 31 + *ip++;
266
3.52k
                    NEED_IP(2);
267
3.52k
                }
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
31.8k
                m_pos = op - 1;
284
31.8k
                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
31.8k
#endif /* COPY_DICT */
290
31.8k
                ip += 2;
291
31.8k
            }
292
33.4k
            else if (t >= 16)           /* a M4 match */
293
8.18k
            {
294
#if defined(COPY_DICT)
295
                m_off = (t & 8) << 11;
296
#else /* !COPY_DICT */
297
8.18k
                m_pos = op;
298
8.18k
                m_pos -= (t & 8) << 11;
299
8.18k
#endif /* COPY_DICT */
300
8.18k
                t &= 7;
301
8.18k
                if (t == 0)
302
2.49k
                {
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
2.47k
                    t += 7 + *ip++;
311
2.47k
                    NEED_IP(2);
312
2.47k
                }
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
8.14k
                m_pos -= UA_GET_LE16(ip) >> 2;
331
#else
332
                m_pos -= (ip[0] >> 2) + (ip[1] << 6);
333
#endif
334
8.14k
                ip += 2;
335
8.14k
                if (m_pos == op)
336
13
                    goto eof_found;
337
8.13k
                m_pos -= 0x4000;
338
#if defined(LZO1Z)
339
                last_m_off = pd((const lzo_bytep)op, m_pos);
340
#endif
341
8.13k
#endif /* COPY_DICT */
342
8.13k
            }
343
25.2k
            else                            /* a M1 match */
344
25.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
25.2k
                m_pos = op - 1;
361
25.2k
                m_pos -= t >> 2;
362
25.2k
                m_pos -= *ip++ << 2;
363
25.2k
#endif
364
25.2k
                TEST_LB(m_pos); NEED_OP(2);
365
25.2k
                *op++ = *m_pos++; *op++ = *m_pos;
366
25.2k
#endif /* COPY_DICT */
367
25.2k
                goto match_done;
368
25.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
39.9k
            TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
379
39.8k
#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32)
380
39.8k
            if (op - m_pos >= 8)
381
36.7k
            {
382
36.7k
                t += (3 - 1);
383
36.7k
                if (t >= 8) do
384
589k
                {
385
589k
                    UA_COPY8(op,m_pos);
386
589k
                    op += 8; m_pos += 8; t -= 8;
387
589k
                } while (t >= 8);
388
36.7k
                if (t >= 4)
389
22.2k
                {
390
22.2k
                    UA_COPY4(op,m_pos);
391
22.2k
                    op += 4; m_pos += 4; t -= 4;
392
22.2k
                }
393
36.7k
                if (t > 0)
394
28.2k
                {
395
28.2k
                    *op++ = m_pos[0];
396
28.2k
                    if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } }
397
28.2k
                }
398
36.7k
            }
399
3.14k
            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.14k
            {
420
64.8k
copy_match:
421
64.8k
                *op++ = *m_pos++; *op++ = *m_pos++;
422
11.9M
                do *op++ = *m_pos++; while (--t > 0);
423
64.8k
            }
424
425
39.8k
#endif /* COPY_DICT */
426
427
135k
match_done:
428
#if defined(LZO1Z)
429
            t = ip[-1] & 3;
430
#else
431
135k
            t = ip[-2] & 3;
432
135k
#endif
433
135k
            if (t == 0)
434
49.9k
                break;
435
436
            /* copy literals */
437
86.2k
match_next:
438
86.2k
            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
86.1k
            *op++ = *ip++;
443
86.1k
            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
444
86.1k
#endif
445
86.1k
            t = *ip++;
446
86.1k
        }
447
0
    }
448
449
13
eof_found:
450
13
    *out_len = pd(op, out);
451
13
    return (ip == ip_end ? LZO_E_OK :
452
13
           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
453
454
455
0
#if defined(HAVE_NEED_IP)
456
398
input_overrun:
457
398
    *out_len = pd(op, out);
458
398
    return LZO_E_INPUT_OVERRUN;
459
0
#endif
460
461
0
#if defined(HAVE_NEED_OP)
462
66
output_overrun:
463
66
    *out_len = pd(op, out);
464
66
    return LZO_E_OUTPUT_OVERRUN;
465
0
#endif
466
467
0
#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
468
146
lookbehind_overrun:
469
146
    *out_len = pd(op, out);
470
146
    return LZO_E_LOOKBEHIND_OVERRUN;
471
248
#endif
472
248
}
lzo1y_decompress_safe
Line
Count
Source
42
636
{
43
636
    lzo_bytep op;
44
636
    const lzo_bytep ip;
45
636
    lzo_uint t;
46
#if defined(COPY_DICT)
47
    lzo_uint m_off;
48
    const lzo_bytep dict_end;
49
#else
50
636
    const lzo_bytep m_pos;
51
636
#endif
52
53
636
    const lzo_bytep const ip_end = in + in_len;
54
636
#if defined(HAVE_ANY_OP)
55
636
    lzo_bytep const op_end = out + *out_len;
56
636
#endif
57
#if defined(LZO1Z)
58
    lzo_uint last_m_off = 0;
59
#endif
60
61
636
    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
636
    *out_len = 0;
81
82
636
    op = out;
83
636
    ip = in;
84
85
636
    NEED_IP(1);
86
636
    if (*ip > 17)
87
369
    {
88
369
        t = *ip++ - 17;
89
369
        if (t < 4)
90
264
            goto match_next;
91
369
        assert(t > 0); NEED_OP(t); NEED_IP(t+3);
92
2.44k
        do *op++ = *ip++; while (--t > 0);
93
92
        goto first_literal_run;
94
105
    }
95
96
267
    for (;;)
97
93.4k
    {
98
93.4k
        NEED_IP(3);
99
93.3k
        t = *ip++;
100
93.3k
        if (t >= 16)
101
68.5k
            goto match;
102
        /* a literal run */
103
24.8k
        if (t == 0)
104
14.9k
        {
105
18.5M
            while (*ip == 0)
106
18.4M
            {
107
18.4M
                t += 255;
108
18.4M
                ip++;
109
18.4M
                TEST_IV(t);
110
18.4M
                NEED_IP(1);
111
18.4M
            }
112
14.9k
            t += 15 + *ip++;
113
14.9k
        }
114
        /* copy literals */
115
24.8k
        assert(t > 0); NEED_OP(t+3); NEED_IP(t+6);
116
24.6k
#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32)
117
24.6k
        t += 3;
118
24.6k
        if (t >= 8) do
119
602k
        {
120
602k
            UA_COPY8(op,ip);
121
602k
            op += 8; ip += 8; t -= 8;
122
602k
        } while (t >= 8);
123
24.6k
        if (t >= 4)
124
13.3k
        {
125
13.3k
            UA_COPY4(op,ip);
126
13.3k
            op += 4; ip += 4; t -= 4;
127
13.3k
        }
128
24.6k
        if (t > 0)
129
19.4k
        {
130
19.4k
            *op++ = *ip++;
131
19.4k
            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
132
19.4k
        }
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
24.7k
first_literal_run:
167
168
169
24.7k
        t = *ip++;
170
24.7k
        if (t >= 16)
171
11.0k
            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
13.7k
        m_pos = op - (1 + M2_MAX_OFFSET);
188
13.7k
        m_pos -= t >> 2;
189
13.7k
        m_pos -= *ip++ << 2;
190
13.7k
#endif
191
13.7k
        TEST_LB(m_pos); NEED_OP(3);
192
13.7k
        *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;
193
13.7k
#endif /* COPY_DICT */
194
13.7k
        goto match_done;
195
196
197
        /* handle matches */
198
121k
        for (;;) {
199
200k
match:
200
200k
            if (t >= 64)                /* a M2 match */
201
97.7k
            {
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
97.7k
                m_pos -= (t >> 2) & 3;
229
97.7k
                m_pos -= *ip++ << 2;
230
97.7k
                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
97.7k
                TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
250
97.6k
                goto copy_match;
251
97.7k
#endif /* COPY_DICT */
252
97.7k
            }
253
102k
            else if (t >= 32)           /* a M3 match */
254
35.0k
            {
255
35.0k
                t &= 31;
256
35.0k
                if (t == 0)
257
2.96k
                {
258
16.1M
                    while (*ip == 0)
259
16.1M
                    {
260
16.1M
                        t += 255;
261
16.1M
                        ip++;
262
16.1M
                        TEST_OV(t);
263
16.1M
                        NEED_IP(1);
264
16.1M
                    }
265
2.94k
                    t += 31 + *ip++;
266
2.94k
                    NEED_IP(2);
267
2.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
                {
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
35.0k
                m_pos = op - 1;
284
35.0k
                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
35.0k
#endif /* COPY_DICT */
290
35.0k
                ip += 2;
291
35.0k
            }
292
67.7k
            else if (t >= 16)           /* a M4 match */
293
10.4k
            {
294
#if defined(COPY_DICT)
295
                m_off = (t & 8) << 11;
296
#else /* !COPY_DICT */
297
10.4k
                m_pos = op;
298
10.4k
                m_pos -= (t & 8) << 11;
299
10.4k
#endif /* COPY_DICT */
300
10.4k
                t &= 7;
301
10.4k
                if (t == 0)
302
2.75k
                {
303
6.03M
                    while (*ip == 0)
304
6.03M
                    {
305
6.03M
                        t += 255;
306
6.03M
                        ip++;
307
6.03M
                        TEST_OV(t);
308
6.03M
                        NEED_IP(1);
309
6.03M
                    }
310
2.73k
                    t += 7 + *ip++;
311
2.73k
                    NEED_IP(2);
312
2.73k
                }
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
10.3k
                m_pos -= UA_GET_LE16(ip) >> 2;
331
#else
332
                m_pos -= (ip[0] >> 2) + (ip[1] << 6);
333
#endif
334
10.3k
                ip += 2;
335
10.3k
                if (m_pos == op)
336
17
                    goto eof_found;
337
10.3k
                m_pos -= 0x4000;
338
#if defined(LZO1Z)
339
                last_m_off = pd((const lzo_bytep)op, m_pos);
340
#endif
341
10.3k
#endif /* COPY_DICT */
342
10.3k
            }
343
57.3k
            else                            /* a M1 match */
344
57.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
57.3k
                m_pos = op - 1;
361
57.3k
                m_pos -= t >> 2;
362
57.3k
                m_pos -= *ip++ << 2;
363
57.3k
#endif
364
57.3k
                TEST_LB(m_pos); NEED_OP(2);
365
57.3k
                *op++ = *m_pos++; *op++ = *m_pos;
366
57.3k
#endif /* COPY_DICT */
367
57.3k
                goto match_done;
368
57.3k
            }
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
45.4k
            TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
379
45.3k
#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32)
380
45.3k
            if (op - m_pos >= 8)
381
41.5k
            {
382
41.5k
                t += (3 - 1);
383
41.5k
                if (t >= 8) do
384
472k
                {
385
472k
                    UA_COPY8(op,m_pos);
386
472k
                    op += 8; m_pos += 8; t -= 8;
387
472k
                } while (t >= 8);
388
41.5k
                if (t >= 4)
389
22.6k
                {
390
22.6k
                    UA_COPY4(op,m_pos);
391
22.6k
                    op += 4; m_pos += 4; t -= 4;
392
22.6k
                }
393
41.5k
                if (t > 0)
394
30.3k
                {
395
30.3k
                    *op++ = m_pos[0];
396
30.3k
                    if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } }
397
30.3k
                }
398
41.5k
            }
399
3.71k
            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.71k
            {
420
101k
copy_match:
421
101k
                *op++ = *m_pos++; *op++ = *m_pos++;
422
11.3M
                do *op++ = *m_pos++; while (--t > 0);
423
101k
            }
424
425
45.3k
#endif /* COPY_DICT */
426
427
214k
match_done:
428
#if defined(LZO1Z)
429
            t = ip[-1] & 3;
430
#else
431
214k
            t = ip[-2] & 3;
432
214k
#endif
433
214k
            if (t == 0)
434
93.1k
                break;
435
436
            /* copy literals */
437
121k
match_next:
438
121k
            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
121k
            *op++ = *ip++;
443
121k
            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
444
121k
#endif
445
121k
            t = *ip++;
446
121k
        }
447
0
    }
448
449
17
eof_found:
450
17
    *out_len = pd(op, out);
451
17
    return (ip == ip_end ? LZO_E_OK :
452
17
           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
453
454
455
0
#if defined(HAVE_NEED_IP)
456
378
input_overrun:
457
378
    *out_len = pd(op, out);
458
378
    return LZO_E_INPUT_OVERRUN;
459
0
#endif
460
461
0
#if defined(HAVE_NEED_OP)
462
64
output_overrun:
463
64
    *out_len = pd(op, out);
464
64
    return LZO_E_OUTPUT_OVERRUN;
465
0
#endif
466
467
0
#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
468
177
lookbehind_overrun:
469
177
    *out_len = pd(op, out);
470
177
    return LZO_E_LOOKBEHIND_OVERRUN;
471
267
#endif
472
267
}
lzo1z_decompress_safe
Line
Count
Source
42
631
{
43
631
    lzo_bytep op;
44
631
    const lzo_bytep ip;
45
631
    lzo_uint t;
46
#if defined(COPY_DICT)
47
    lzo_uint m_off;
48
    const lzo_bytep dict_end;
49
#else
50
631
    const lzo_bytep m_pos;
51
631
#endif
52
53
631
    const lzo_bytep const ip_end = in + in_len;
54
631
#if defined(HAVE_ANY_OP)
55
631
    lzo_bytep const op_end = out + *out_len;
56
631
#endif
57
631
#if defined(LZO1Z)
58
631
    lzo_uint last_m_off = 0;
59
631
#endif
60
61
631
    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
631
    *out_len = 0;
81
82
631
    op = out;
83
631
    ip = in;
84
85
631
    NEED_IP(1);
86
631
    if (*ip > 17)
87
431
    {
88
431
        t = *ip++ - 17;
89
431
        if (t < 4)
90
320
            goto match_next;
91
431
        assert(t > 0); NEED_OP(t); NEED_IP(t+3);
92
1.76k
        do *op++ = *ip++; while (--t > 0);
93
98
        goto first_literal_run;
94
111
    }
95
96
200
    for (;;)
97
47.6k
    {
98
47.6k
        NEED_IP(3);
99
47.6k
        t = *ip++;
100
47.6k
        if (t >= 16)
101
34.3k
            goto match;
102
        /* a literal run */
103
13.3k
        if (t == 0)
104
5.91k
        {
105
3.00M
            while (*ip == 0)
106
2.99M
            {
107
2.99M
                t += 255;
108
2.99M
                ip++;
109
2.99M
                TEST_IV(t);
110
2.99M
                NEED_IP(1);
111
2.99M
            }
112
5.89k
            t += 15 + *ip++;
113
5.89k
        }
114
        /* copy literals */
115
13.3k
        assert(t > 0); NEED_OP(t+3); NEED_IP(t+6);
116
13.1k
#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32)
117
13.1k
        t += 3;
118
13.1k
        if (t >= 8) do
119
443k
        {
120
443k
            UA_COPY8(op,ip);
121
443k
            op += 8; ip += 8; t -= 8;
122
443k
        } while (t >= 8);
123
13.1k
        if (t >= 4)
124
7.47k
        {
125
7.47k
            UA_COPY4(op,ip);
126
7.47k
            op += 4; ip += 4; t -= 4;
127
7.47k
        }
128
13.1k
        if (t > 0)
129
9.02k
        {
130
9.02k
            *op++ = *ip++;
131
9.02k
            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
132
9.02k
        }
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
13.2k
first_literal_run:
167
168
169
13.2k
        t = *ip++;
170
13.2k
        if (t >= 16)
171
6.43k
            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
6.78k
#if defined(LZO1Z)
183
6.78k
        t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
184
6.78k
        m_pos = op - t;
185
6.78k
        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
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
108k
        for (;;) {
199
149k
match:
200
149k
            if (t >= 64)                /* a M2 match */
201
85.6k
            {
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
85.6k
                    lzo_uint off = t & 0x1f;
234
85.6k
                    m_pos = op;
235
85.6k
                    if (off >= 0x1c)
236
12.3k
                    {
237
12.3k
                        assert(last_m_off > 0);
238
12.3k
                        m_pos -= last_m_off;
239
12.3k
                    }
240
73.3k
                    else
241
73.3k
                    {
242
73.3k
                        off = 1 + (off << 6) + (*ip++ >> 2);
243
73.3k
                        m_pos -= off;
244
73.3k
                        last_m_off = off;
245
73.3k
                    }
246
85.6k
                }
247
85.6k
                t = (t >> 5) - 1;
248
85.6k
#endif
249
85.6k
                TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
250
85.6k
                goto copy_match;
251
85.6k
#endif /* COPY_DICT */
252
85.6k
            }
253
63.6k
            else if (t >= 32)           /* a M3 match */
254
20.3k
            {
255
20.3k
                t &= 31;
256
20.3k
                if (t == 0)
257
3.59k
                {
258
1.68M
                    while (*ip == 0)
259
1.68M
                    {
260
1.68M
                        t += 255;
261
1.68M
                        ip++;
262
1.68M
                        TEST_OV(t);
263
1.68M
                        NEED_IP(1);
264
1.68M
                    }
265
3.57k
                    t += 31 + *ip++;
266
3.57k
                    NEED_IP(2);
267
3.57k
                }
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
20.2k
#if defined(LZO1Z)
277
20.2k
                {
278
20.2k
                    lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2);
279
20.2k
                    m_pos = op - off;
280
20.2k
                    last_m_off = off;
281
20.2k
                }
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
20.2k
#endif /* COPY_DICT */
290
20.2k
                ip += 2;
291
20.2k
            }
292
43.3k
            else if (t >= 16)           /* a M4 match */
293
6.36k
            {
294
#if defined(COPY_DICT)
295
                m_off = (t & 8) << 11;
296
#else /* !COPY_DICT */
297
6.36k
                m_pos = op;
298
6.36k
                m_pos -= (t & 8) << 11;
299
6.36k
#endif /* COPY_DICT */
300
6.36k
                t &= 7;
301
6.36k
                if (t == 0)
302
2.44k
                {
303
80.6k
                    while (*ip == 0)
304
78.2k
                    {
305
78.2k
                        t += 255;
306
78.2k
                        ip++;
307
78.2k
                        TEST_OV(t);
308
78.2k
                        NEED_IP(1);
309
78.2k
                    }
310
2.43k
                    t += 7 + *ip++;
311
2.43k
                    NEED_IP(2);
312
2.43k
                }
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
6.35k
#if defined(LZO1Z)
328
6.35k
                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
6.35k
                ip += 2;
335
6.35k
                if (m_pos == op)
336
16
                    goto eof_found;
337
6.33k
                m_pos -= 0x4000;
338
6.33k
#if defined(LZO1Z)
339
6.33k
                last_m_off = pd((const lzo_bytep)op, m_pos);
340
6.33k
#endif
341
6.33k
#endif /* COPY_DICT */
342
6.33k
            }
343
36.9k
            else                            /* a M1 match */
344
36.9k
            {
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
36.9k
#if defined(LZO1Z)
356
36.9k
                t = 1 + (t << 6) + (*ip++ >> 2);
357
36.9k
                m_pos = op - t;
358
36.9k
                last_m_off = t;
359
#else
360
                m_pos = op - 1;
361
                m_pos -= t >> 2;
362
                m_pos -= *ip++ << 2;
363
#endif
364
36.9k
                TEST_LB(m_pos); NEED_OP(2);
365
36.9k
                *op++ = *m_pos++; *op++ = *m_pos;
366
36.9k
#endif /* COPY_DICT */
367
36.9k
                goto match_done;
368
36.9k
            }
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
26.6k
            TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
379
26.5k
#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32)
380
26.5k
            if (op - m_pos >= 8)
381
23.8k
            {
382
23.8k
                t += (3 - 1);
383
23.8k
                if (t >= 8) do
384
1.09M
                {
385
1.09M
                    UA_COPY8(op,m_pos);
386
1.09M
                    op += 8; m_pos += 8; t -= 8;
387
1.09M
                } while (t >= 8);
388
23.8k
                if (t >= 4)
389
12.5k
                {
390
12.5k
                    UA_COPY4(op,m_pos);
391
12.5k
                    op += 4; m_pos += 4; t -= 4;
392
12.5k
                }
393
23.8k
                if (t > 0)
394
19.7k
                {
395
19.7k
                    *op++ = m_pos[0];
396
19.7k
                    if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } }
397
19.7k
                }
398
23.8k
            }
399
2.67k
            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.67k
            {
420
88.3k
copy_match:
421
88.3k
                *op++ = *m_pos++; *op++ = *m_pos++;
422
6.91M
                do *op++ = *m_pos++; while (--t > 0);
423
88.3k
            }
424
425
26.5k
#endif /* COPY_DICT */
426
427
155k
match_done:
428
155k
#if defined(LZO1Z)
429
155k
            t = ip[-1] & 3;
430
#else
431
            t = ip[-2] & 3;
432
#endif
433
155k
            if (t == 0)
434
47.4k
                break;
435
436
            /* copy literals */
437
108k
match_next:
438
108k
            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
108k
            *op++ = *ip++;
443
108k
            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
444
108k
#endif
445
108k
            t = *ip++;
446
108k
        }
447
0
    }
448
449
16
eof_found:
450
16
    *out_len = pd(op, out);
451
16
    return (ip == ip_end ? LZO_E_OK :
452
16
           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
453
454
455
0
#if defined(HAVE_NEED_IP)
456
401
input_overrun:
457
401
    *out_len = pd(op, out);
458
401
    return LZO_E_INPUT_OVERRUN;
459
0
#endif
460
461
0
#if defined(HAVE_NEED_OP)
462
61
output_overrun:
463
61
    *out_len = pd(op, out);
464
61
    return LZO_E_OUTPUT_OVERRUN;
465
0
#endif
466
467
0
#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
468
153
lookbehind_overrun:
469
153
    *out_len = pd(op, out);
470
153
    return LZO_E_LOOKBEHIND_OVERRUN;
471
200
#endif
472
200
}
473
474
475
/* vim:set ts=4 sw=4 et: */