opencv

Форк
0
/
infback.c 
511 строк · 18.5 Кб
1
/* infback.c -- inflate using a call-back interface
2
 * Copyright (C) 1995-2022 Mark Adler
3
 * For conditions of distribution and use, see copyright notice in zlib.h
4
 */
5

6
/*
7
   This code is largely copied from inflate.c.  Normally either infback.o or
8
   inflate.o would be linked into an application--not both.  The interface
9
   with inffast.c is retained so that optimized assembler-coded versions of
10
   inflate_fast() can be used with either inflate.c or infback.c.
11
 */
12

13
#include "zbuild.h"
14
#include "zutil.h"
15
#include "inftrees.h"
16
#include "inflate.h"
17
#include "inflate_p.h"
18
#include "functable.h"
19

20
/* Avoid conflicts with zlib.h macros */
21
#ifdef ZLIB_COMPAT
22
# undef inflateBackInit
23
#endif
24

25
/*
26
   strm provides memory allocation functions in zalloc and zfree, or
27
   NULL to use the library memory allocation functions.
28

29
   windowBits is in the range 8..15, and window is a user-supplied
30
   window and output buffer that is 2**windowBits bytes.
31

32
   This function is hidden in ZLIB_COMPAT builds.
33
 */
34
int32_t ZNG_CONDEXPORT PREFIX(inflateBackInit)(PREFIX3(stream) *strm, int32_t windowBits, uint8_t *window) {
35
    struct inflate_state *state;
36

37
    if (strm == NULL || window == NULL || windowBits < MIN_WBITS || windowBits > MAX_WBITS)
38
        return Z_STREAM_ERROR;
39
    strm->msg = NULL;                   /* in case we return an error */
40
    if (strm->zalloc == NULL) {
41
        strm->zalloc = PREFIX(zcalloc);
42
        strm->opaque = NULL;
43
    }
44
    if (strm->zfree == NULL)
45
        strm->zfree = PREFIX(zcfree);
46
    state = ZALLOC_INFLATE_STATE(strm);
47
    if (state == NULL)
48
        return Z_MEM_ERROR;
49
    Tracev((stderr, "inflate: allocated\n"));
50
    strm->state = (struct internal_state *)state;
51
    state->dmax = 32768U;
52
    state->wbits = (unsigned int)windowBits;
53
    state->wsize = 1U << windowBits;
54
    state->window = window;
55
    state->wnext = 0;
56
    state->whave = 0;
57
    state->sane = 1;
58
    state->chunksize = functable.chunksize();
59
    return Z_OK;
60
}
61

62
/* Function used by zlib.h and zlib-ng version 2.0 macros */
63
int32_t Z_EXPORT PREFIX(inflateBackInit_)(PREFIX3(stream) *strm, int32_t windowBits, uint8_t *window,
64
                              const char *version, int32_t stream_size) {
65
    if (CHECK_VER_STSIZE(version, stream_size))
66
        return Z_VERSION_ERROR;
67
    return PREFIX(inflateBackInit)(strm, windowBits, window);
68
}
69

70
/*
71
   Private macros for inflateBack()
72
   Look in inflate_p.h for macros shared with inflate()
73
*/
74

75
/* Assure that some input is available.  If input is requested, but denied,
76
   then return a Z_BUF_ERROR from inflateBack(). */
77
#define PULL() \
78
    do { \
79
        if (have == 0) { \
80
            have = in(in_desc, &next); \
81
            if (have == 0) { \
82
                next = NULL; \
83
                ret = Z_BUF_ERROR; \
84
                goto inf_leave; \
85
            } \
86
        } \
87
    } while (0)
88

89
/* Get a byte of input into the bit accumulator, or return from inflateBack()
90
   with an error if there is no input available. */
91
#define PULLBYTE() \
92
    do { \
93
        PULL(); \
94
        have--; \
95
        hold += ((unsigned)(*next++) << bits); \
96
        bits += 8; \
97
    } while (0)
98

99
/* Assure that some output space is available, by writing out the window
100
   if it's full.  If the write fails, return from inflateBack() with a
101
   Z_BUF_ERROR. */
102
#define ROOM() \
103
    do { \
104
        if (left == 0) { \
105
            put = state->window; \
106
            left = state->wsize; \
107
            state->whave = left; \
108
            if (out(out_desc, put, left)) { \
109
                ret = Z_BUF_ERROR; \
110
                goto inf_leave; \
111
            } \
112
        } \
113
    } while (0)
114

115
/*
116
   strm provides the memory allocation functions and window buffer on input,
117
   and provides information on the unused input on return.  For Z_DATA_ERROR
118
   returns, strm will also provide an error message.
119

120
   in() and out() are the call-back input and output functions.  When
121
   inflateBack() needs more input, it calls in().  When inflateBack() has
122
   filled the window with output, or when it completes with data in the
123
   window, it calls out() to write out the data.  The application must not
124
   change the provided input until in() is called again or inflateBack()
125
   returns.  The application must not change the window/output buffer until
126
   inflateBack() returns.
127

128
   in() and out() are called with a descriptor parameter provided in the
129
   inflateBack() call.  This parameter can be a structure that provides the
130
   information required to do the read or write, as well as accumulated
131
   information on the input and output such as totals and check values.
132

133
   in() should return zero on failure.  out() should return non-zero on
134
   failure.  If either in() or out() fails, than inflateBack() returns a
135
   Z_BUF_ERROR.  strm->next_in can be checked for NULL to see whether it
136
   was in() or out() that caused in the error.  Otherwise, inflateBack()
137
   returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
138
   error, or Z_MEM_ERROR if it could not allocate memory for the state.
139
   inflateBack() can also return Z_STREAM_ERROR if the input parameters
140
   are not correct, i.e. strm is NULL or the state was not initialized.
141
 */
142
int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in_desc, out_func out, void *out_desc) {
143
    struct inflate_state *state;
144
    z_const unsigned char *next; /* next input */
145
    unsigned char *put;          /* next output */
146
    unsigned have, left;         /* available input and output */
147
    uint32_t hold;               /* bit buffer */
148
    unsigned bits;               /* bits in bit buffer */
149
    unsigned copy;               /* number of stored or match bytes to copy */
150
    unsigned char *from;         /* where to copy match bytes from */
151
    code here;                   /* current decoding table entry */
152
    code last;                   /* parent table entry */
153
    unsigned len;                /* length to copy for repeats, bits to drop */
154
    int32_t ret;                 /* return code */
155
    static const uint16_t order[19] = /* permutation of code lengths */
156
        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
157

158
    /* Check that the strm exists and that the state was initialized */
159
    if (strm == NULL || strm->state == NULL)
160
        return Z_STREAM_ERROR;
161
    state = (struct inflate_state *)strm->state;
162

163
    /* Reset the state */
164
    strm->msg = NULL;
165
    state->mode = TYPE;
166
    state->last = 0;
167
    state->whave = 0;
168
    next = strm->next_in;
169
    have = next != NULL ? strm->avail_in : 0;
170
    hold = 0;
171
    bits = 0;
172
    put = state->window;
173
    left = state->wsize;
174

175
    /* Inflate until end of block marked as last */
176
    for (;;)
177
        switch (state->mode) {
178
        case TYPE:
179
            /* determine and dispatch block type */
180
            if (state->last) {
181
                BYTEBITS();
182
                state->mode = DONE;
183
                break;
184
            }
185
            NEEDBITS(3);
186
            state->last = BITS(1);
187
            DROPBITS(1);
188
            switch (BITS(2)) {
189
            case 0:                             /* stored block */
190
                Tracev((stderr, "inflate:     stored block%s\n", state->last ? " (last)" : ""));
191
                state->mode = STORED;
192
                break;
193
            case 1:                             /* fixed block */
194
                PREFIX(fixedtables)(state);
195
                Tracev((stderr, "inflate:     fixed codes block%s\n", state->last ? " (last)" : ""));
196
                state->mode = LEN;              /* decode codes */
197
                break;
198
            case 2:                             /* dynamic block */
199
                Tracev((stderr, "inflate:     dynamic codes block%s\n", state->last ? " (last)" : ""));
200
                state->mode = TABLE;
201
                break;
202
            case 3:
203
                SET_BAD("invalid block type");
204
            }
205
            DROPBITS(2);
206
            break;
207

208
        case STORED:
209
            /* get and verify stored block length */
210
            BYTEBITS();                         /* go to byte boundary */
211
            NEEDBITS(32);
212
            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
213
                SET_BAD("invalid stored block lengths");
214
                break;
215
            }
216
            state->length = (uint16_t)hold;
217
            Tracev((stderr, "inflate:       stored length %u\n", state->length));
218
            INITBITS();
219

220
            /* copy stored block from input to output */
221
            while (state->length != 0) {
222
                copy = state->length;
223
                PULL();
224
                ROOM();
225
                copy = MIN(copy, have);
226
                copy = MIN(copy, left);
227
                memcpy(put, next, copy);
228
                have -= copy;
229
                next += copy;
230
                left -= copy;
231
                put += copy;
232
                state->length -= copy;
233
            }
234
            Tracev((stderr, "inflate:       stored end\n"));
235
            state->mode = TYPE;
236
            break;
237

238
        case TABLE:
239
            /* get dynamic table entries descriptor */
240
            NEEDBITS(14);
241
            state->nlen = BITS(5) + 257;
242
            DROPBITS(5);
243
            state->ndist = BITS(5) + 1;
244
            DROPBITS(5);
245
            state->ncode = BITS(4) + 4;
246
            DROPBITS(4);
247
#ifndef PKZIP_BUG_WORKAROUND
248
            if (state->nlen > 286 || state->ndist > 30) {
249
                SET_BAD("too many length or distance symbols");
250
                break;
251
            }
252
#endif
253
            Tracev((stderr, "inflate:       table sizes ok\n"));
254
            state->have = 0;
255

256
            /* get code length code lengths (not a typo) */
257
            while (state->have < state->ncode) {
258
                NEEDBITS(3);
259
                state->lens[order[state->have++]] = (uint16_t)BITS(3);
260
                DROPBITS(3);
261
            }
262
            while (state->have < 19)
263
                state->lens[order[state->have++]] = 0;
264
            state->next = state->codes;
265
            state->lencode = (const code *)(state->next);
266
            state->lenbits = 7;
267
            ret = zng_inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work);
268
            if (ret) {
269
                SET_BAD("invalid code lengths set");
270
                break;
271
            }
272
            Tracev((stderr, "inflate:       code lengths ok\n"));
273
            state->have = 0;
274

275
            /* get length and distance code code lengths */
276
            while (state->have < state->nlen + state->ndist) {
277
                for (;;) {
278
                    here = state->lencode[BITS(state->lenbits)];
279
                    if (here.bits <= bits) break;
280
                    PULLBYTE();
281
                }
282
                if (here.val < 16) {
283
                    DROPBITS(here.bits);
284
                    state->lens[state->have++] = here.val;
285
                } else {
286
                    if (here.val == 16) {
287
                        NEEDBITS(here.bits + 2);
288
                        DROPBITS(here.bits);
289
                        if (state->have == 0) {
290
                            SET_BAD("invalid bit length repeat");
291
                            break;
292
                        }
293
                        len = state->lens[state->have - 1];
294
                        copy = 3 + BITS(2);
295
                        DROPBITS(2);
296
                    } else if (here.val == 17) {
297
                        NEEDBITS(here.bits + 3);
298
                        DROPBITS(here.bits);
299
                        len = 0;
300
                        copy = 3 + BITS(3);
301
                        DROPBITS(3);
302
                    } else {
303
                        NEEDBITS(here.bits + 7);
304
                        DROPBITS(here.bits);
305
                        len = 0;
306
                        copy = 11 + BITS(7);
307
                        DROPBITS(7);
308
                    }
309
                    if (state->have + copy > state->nlen + state->ndist) {
310
                        SET_BAD("invalid bit length repeat");
311
                        break;
312
                    }
313
                    while (copy) {
314
                        --copy;
315
                        state->lens[state->have++] = (uint16_t)len;
316
                    }
317
                }
318
            }
319

320
            /* handle error breaks in while */
321
            if (state->mode == BAD)
322
                break;
323

324
            /* check for end-of-block code (better have one) */
325
            if (state->lens[256] == 0) {
326
                SET_BAD("invalid code -- missing end-of-block");
327
                break;
328
            }
329

330
            /* build code tables -- note: do not change the lenbits or distbits
331
               values here (10 and 9) without reading the comments in inftrees.h
332
               concerning the ENOUGH constants, which depend on those values */
333
            state->next = state->codes;
334
            state->lencode = (const code *)(state->next);
335
            state->lenbits = 10;
336
            ret = zng_inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work);
337
            if (ret) {
338
                SET_BAD("invalid literal/lengths set");
339
                break;
340
            }
341
            state->distcode = (const code *)(state->next);
342
            state->distbits = 9;
343
            ret = zng_inflate_table(DISTS, state->lens + state->nlen, state->ndist,
344
                                &(state->next), &(state->distbits), state->work);
345
            if (ret) {
346
                SET_BAD("invalid distances set");
347
                break;
348
            }
349
            Tracev((stderr, "inflate:       codes ok\n"));
350
            state->mode = LEN;
351
            Z_FALLTHROUGH;
352

353
        case LEN:
354
            /* use inflate_fast() if we have enough input and output */
355
            if (have >= INFLATE_FAST_MIN_HAVE &&
356
                left >= INFLATE_FAST_MIN_LEFT) {
357
                RESTORE();
358
                if (state->whave < state->wsize)
359
                    state->whave = state->wsize - left;
360
                functable.inflate_fast(strm, state->wsize);
361
                LOAD();
362
                break;
363
            }
364

365
            /* get a literal, length, or end-of-block code */
366
            for (;;) {
367
                here = state->lencode[BITS(state->lenbits)];
368
                if (here.bits <= bits)
369
                    break;
370
                PULLBYTE();
371
            }
372
            if (here.op && (here.op & 0xf0) == 0) {
373
                last = here;
374
                for (;;) {
375
                    here = state->lencode[last.val + (BITS(last.bits + last.op) >> last.bits)];
376
                    if ((unsigned)last.bits + (unsigned)here.bits <= bits)
377
                        break;
378
                    PULLBYTE();
379
                }
380
                DROPBITS(last.bits);
381
            }
382
            DROPBITS(here.bits);
383
            state->length = here.val;
384

385
            /* process literal */
386
            if ((int)(here.op) == 0) {
387
                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
388
                        "inflate:         literal '%c'\n" :
389
                        "inflate:         literal 0x%02x\n", here.val));
390
                ROOM();
391
                *put++ = (unsigned char)(state->length);
392
                left--;
393
                state->mode = LEN;
394
                break;
395
            }
396

397
            /* process end of block */
398
            if (here.op & 32) {
399
                Tracevv((stderr, "inflate:         end of block\n"));
400
                state->mode = TYPE;
401
                break;
402
            }
403

404
            /* invalid code */
405
            if (here.op & 64) {
406
                SET_BAD("invalid literal/length code");
407
                break;
408
            }
409

410
            /* length code -- get extra bits, if any */
411
            state->extra = (here.op & MAX_BITS);
412
            if (state->extra) {
413
                NEEDBITS(state->extra);
414
                state->length += BITS(state->extra);
415
                DROPBITS(state->extra);
416
            }
417
            Tracevv((stderr, "inflate:         length %u\n", state->length));
418

419
            /* get distance code */
420
            for (;;) {
421
                here = state->distcode[BITS(state->distbits)];
422
                if (here.bits <= bits)
423
                    break;
424
                PULLBYTE();
425
            }
426
            if ((here.op & 0xf0) == 0) {
427
                last = here;
428
                for (;;) {
429
                    here = state->distcode[last.val + (BITS(last.bits + last.op) >> last.bits)];
430
                    if ((unsigned)last.bits + (unsigned)here.bits <= bits)
431
                        break;
432
                    PULLBYTE();
433
                }
434
                DROPBITS(last.bits);
435
            }
436
            DROPBITS(here.bits);
437
            if (here.op & 64) {
438
                SET_BAD("invalid distance code");
439
                break;
440
            }
441
            state->offset = here.val;
442
            state->extra = (here.op & MAX_BITS);
443

444
            /* get distance extra bits, if any */
445
            if (state->extra) {
446
                NEEDBITS(state->extra);
447
                state->offset += BITS(state->extra);
448
                DROPBITS(state->extra);
449
            }
450
#ifdef INFLATE_STRICT
451
            if (state->offset > state->wsize - (state->whave < state->wsize ? left : 0)) {
452
                SET_BAD("invalid distance too far back");
453
                break;
454
            }
455
#endif
456
            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
457

458
            /* copy match from window to output */
459
            do {
460
                ROOM();
461
                copy = state->wsize - state->offset;
462
                if (copy < left) {
463
                    from = put + copy;
464
                    copy = left - copy;
465
                } else {
466
                    from = put - state->offset;
467
                    copy = left;
468
                }
469
                copy = MIN(copy, state->length);
470
                state->length -= copy;
471
                left -= copy;
472
                do {
473
                    *put++ = *from++;
474
                } while (--copy);
475
            } while (state->length != 0);
476
            break;
477

478
        case DONE:
479
            /* inflate stream terminated properly */
480
            ret = Z_STREAM_END;
481
            goto inf_leave;
482

483
        case BAD:
484
            ret = Z_DATA_ERROR;
485
            goto inf_leave;
486

487
        default:                /* can't happen, but makes compilers happy */
488
            ret = Z_STREAM_ERROR;
489
            goto inf_leave;
490
        }
491

492
    /* Write leftover output and return unused input */
493
  inf_leave:
494
    if (left < state->wsize) {
495
        if (out(out_desc, state->window, state->wsize - left) && (ret == Z_STREAM_END)) {
496
            ret = Z_BUF_ERROR;
497
        }
498
    }
499
    strm->next_in = next;
500
    strm->avail_in = have;
501
    return ret;
502
}
503

504
int32_t Z_EXPORT PREFIX(inflateBackEnd)(PREFIX3(stream) *strm) {
505
    if (strm == NULL || strm->state == NULL || strm->zfree == NULL)
506
        return Z_STREAM_ERROR;
507
    ZFREE_STATE(strm, strm->state);
508
    strm->state = NULL;
509
    Tracev((stderr, "inflate: end\n"));
510
    return Z_OK;
511
}
512

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.