Coverage Report

Created: 2025-06-12 06:51

/src/opencv/3rdparty/zlib/gzlib.c
Line
Count
Source (jump to first uncovered line)
1
/* gzlib.c -- zlib functions common to reading and writing gzip files
2
 * Copyright (C) 2004-2024 Mark Adler
3
 * For conditions of distribution and use, see copyright notice in zlib.h
4
 */
5
6
#include "gzguts.h"
7
8
#if defined(_WIN32) && !defined(__BORLANDC__)
9
#  define LSEEK _lseeki64
10
#else
11
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
12
#  define LSEEK lseek64
13
#else
14
0
#  define LSEEK lseek
15
#endif
16
#endif
17
18
#if defined UNDER_CE
19
20
/* Map the Windows error number in ERROR to a locale-dependent error message
21
   string and return a pointer to it.  Typically, the values for ERROR come
22
   from GetLastError.
23
24
   The string pointed to shall not be modified by the application, but may be
25
   overwritten by a subsequent call to gz_strwinerror
26
27
   The gz_strwinerror function does not change the current setting of
28
   GetLastError. */
29
char ZLIB_INTERNAL *gz_strwinerror(DWORD error) {
30
    static char buf[1024];
31
32
    wchar_t *msgbuf;
33
    DWORD lasterr = GetLastError();
34
    DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
35
        | FORMAT_MESSAGE_ALLOCATE_BUFFER,
36
        NULL,
37
        error,
38
        0, /* Default language */
39
        (LPVOID)&msgbuf,
40
        0,
41
        NULL);
42
    if (chars != 0) {
43
        /* If there is an \r\n appended, zap it.  */
44
        if (chars >= 2
45
            && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
46
            chars -= 2;
47
            msgbuf[chars] = 0;
48
        }
49
50
        if (chars > sizeof (buf) - 1) {
51
            chars = sizeof (buf) - 1;
52
            msgbuf[chars] = 0;
53
        }
54
55
        wcstombs(buf, msgbuf, chars + 1);
56
        LocalFree(msgbuf);
57
    }
58
    else {
59
        sprintf(buf, "unknown win32 error (%ld)", error);
60
    }
61
62
    SetLastError(lasterr);
63
    return buf;
64
}
65
66
#endif /* UNDER_CE */
67
68
/* Reset gzip file state */
69
0
local void gz_reset(gz_statep state) {
70
0
    state->x.have = 0;              /* no output data available */
71
0
    if (state->mode == GZ_READ) {   /* for reading ... */
72
0
        state->eof = 0;             /* not at end of file */
73
0
        state->past = 0;            /* have not read past end yet */
74
0
        state->how = LOOK;          /* look for gzip header */
75
0
    }
76
0
    else                            /* for writing ... */
77
0
        state->reset = 0;           /* no deflateReset pending */
78
0
    state->seek = 0;                /* no seek request pending */
79
0
    gz_error(state, Z_OK, NULL);    /* clear error */
80
0
    state->x.pos = 0;               /* no uncompressed data yet */
81
0
    state->strm.avail_in = 0;       /* no input data yet */
82
0
}
83
84
/* Open a gzip file either by name or file descriptor. */
85
0
local gzFile gz_open(const void *path, int fd, const char *mode) {
86
0
    gz_statep state;
87
0
    z_size_t len;
88
0
    int oflag;
89
0
#ifdef O_CLOEXEC
90
0
    int cloexec = 0;
91
0
#endif
92
0
#ifdef O_EXCL
93
0
    int exclusive = 0;
94
0
#endif
95
96
    /* check input */
97
0
    if (path == NULL)
98
0
        return NULL;
99
100
    /* allocate gzFile structure to return */
101
0
    state = (gz_statep)malloc(sizeof(gz_state));
102
0
    if (state == NULL)
103
0
        return NULL;
104
0
    state->size = 0;            /* no buffers allocated yet */
105
0
    state->want = GZBUFSIZE;    /* requested buffer size */
106
0
    state->msg = NULL;          /* no error message yet */
107
108
    /* interpret mode */
109
0
    state->mode = GZ_NONE;
110
0
    state->level = Z_DEFAULT_COMPRESSION;
111
0
    state->strategy = Z_DEFAULT_STRATEGY;
112
0
    state->direct = 0;
113
0
    while (*mode) {
114
0
        if (*mode >= '0' && *mode <= '9')
115
0
            state->level = *mode - '0';
116
0
        else
117
0
            switch (*mode) {
118
0
            case 'r':
119
0
                state->mode = GZ_READ;
120
0
                break;
121
0
#ifndef NO_GZCOMPRESS
122
0
            case 'w':
123
0
                state->mode = GZ_WRITE;
124
0
                break;
125
0
            case 'a':
126
0
                state->mode = GZ_APPEND;
127
0
                break;
128
0
#endif
129
0
            case '+':       /* can't read and write at the same time */
130
0
                free(state);
131
0
                return NULL;
132
0
            case 'b':       /* ignore -- will request binary anyway */
133
0
                break;
134
0
#ifdef O_CLOEXEC
135
0
            case 'e':
136
0
                cloexec = 1;
137
0
                break;
138
0
#endif
139
0
#ifdef O_EXCL
140
0
            case 'x':
141
0
                exclusive = 1;
142
0
                break;
143
0
#endif
144
0
            case 'f':
145
0
                state->strategy = Z_FILTERED;
146
0
                break;
147
0
            case 'h':
148
0
                state->strategy = Z_HUFFMAN_ONLY;
149
0
                break;
150
0
            case 'R':
151
0
                state->strategy = Z_RLE;
152
0
                break;
153
0
            case 'F':
154
0
                state->strategy = Z_FIXED;
155
0
                break;
156
0
            case 'T':
157
0
                state->direct = 1;
158
0
                break;
159
0
            default:        /* could consider as an error, but just ignore */
160
0
                ;
161
0
            }
162
0
        mode++;
163
0
    }
164
165
    /* must provide an "r", "w", or "a" */
166
0
    if (state->mode == GZ_NONE) {
167
0
        free(state);
168
0
        return NULL;
169
0
    }
170
171
    /* can't force transparent read */
172
0
    if (state->mode == GZ_READ) {
173
0
        if (state->direct) {
174
0
            free(state);
175
0
            return NULL;
176
0
        }
177
0
        state->direct = 1;      /* for empty file */
178
0
    }
179
180
    /* save the path name for error messages */
181
#ifdef WIDECHAR
182
    if (fd == -2) {
183
        len = wcstombs(NULL, path, 0);
184
        if (len == (z_size_t)-1)
185
            len = 0;
186
    }
187
    else
188
#endif
189
0
        len = strlen((const char *)path);
190
0
    state->path = (char *)malloc(len + 1);
191
0
    if (state->path == NULL) {
192
0
        free(state);
193
0
        return NULL;
194
0
    }
195
#ifdef WIDECHAR
196
    if (fd == -2)
197
        if (len)
198
            wcstombs(state->path, path, len + 1);
199
        else
200
            *(state->path) = 0;
201
    else
202
#endif
203
0
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
204
0
        (void)snprintf(state->path, len + 1, "%s", (const char *)path);
205
#else
206
        strcpy(state->path, path);
207
#endif
208
209
    /* compute the flags for open() */
210
0
    oflag =
211
#ifdef O_LARGEFILE
212
        O_LARGEFILE |
213
#endif
214
#ifdef O_BINARY
215
        O_BINARY |
216
#endif
217
0
#ifdef O_CLOEXEC
218
0
        (cloexec ? O_CLOEXEC : 0) |
219
0
#endif
220
0
        (state->mode == GZ_READ ?
221
0
         O_RDONLY :
222
0
         (O_WRONLY | O_CREAT |
223
0
#ifdef O_EXCL
224
0
          (exclusive ? O_EXCL : 0) |
225
0
#endif
226
0
          (state->mode == GZ_WRITE ?
227
0
           O_TRUNC :
228
0
           O_APPEND)));
229
230
    /* open the file with the appropriate flags (or just use fd) */
231
0
    state->fd = fd > -1 ? fd : (
232
#ifdef WIDECHAR
233
        fd == -2 ? _wopen(path, oflag, 0666) :
234
#endif
235
0
        open((const char *)path, oflag, 0666));
236
0
    if (state->fd == -1) {
237
0
        free(state->path);
238
0
        free(state);
239
0
        return NULL;
240
0
    }
241
0
    if (state->mode == GZ_APPEND) {
242
0
        LSEEK(state->fd, 0, SEEK_END);  /* so gzoffset() is correct */
243
0
        state->mode = GZ_WRITE;         /* simplify later checks */
244
0
    }
245
246
    /* save the current position for rewinding (only if reading) */
247
0
    if (state->mode == GZ_READ) {
248
0
        state->start = LSEEK(state->fd, 0, SEEK_CUR);
249
0
        if (state->start == -1) state->start = 0;
250
0
    }
251
252
    /* initialize stream */
253
0
    gz_reset(state);
254
255
    /* return stream */
256
0
    return (gzFile)state;
257
0
}
258
259
/* -- see zlib.h -- */
260
0
gzFile ZEXPORT gzopen(const char *path, const char *mode) {
261
0
    return gz_open(path, -1, mode);
262
0
}
263
264
/* -- see zlib.h -- */
265
0
gzFile ZEXPORT gzopen64(const char *path, const char *mode) {
266
0
    return gz_open(path, -1, mode);
267
0
}
268
269
/* -- see zlib.h -- */
270
0
gzFile ZEXPORT gzdopen(int fd, const char *mode) {
271
0
    char *path;         /* identifier for error messages */
272
0
    gzFile gz;
273
274
0
    if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
275
0
        return NULL;
276
0
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
277
0
    (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd);
278
#else
279
    sprintf(path, "<fd:%d>", fd);   /* for debugging */
280
#endif
281
0
    gz = gz_open(path, fd, mode);
282
0
    free(path);
283
0
    return gz;
284
0
}
285
286
/* -- see zlib.h -- */
287
#ifdef WIDECHAR
288
gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode) {
289
    return gz_open(path, -2, mode);
290
}
291
#endif
292
293
/* -- see zlib.h -- */
294
0
int ZEXPORT gzbuffer(gzFile file, unsigned size) {
295
0
    gz_statep state;
296
297
    /* get internal structure and check integrity */
298
0
    if (file == NULL)
299
0
        return -1;
300
0
    state = (gz_statep)file;
301
0
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
302
0
        return -1;
303
304
    /* make sure we haven't already allocated memory */
305
0
    if (state->size != 0)
306
0
        return -1;
307
308
    /* check and set requested size */
309
0
    if ((size << 1) < size)
310
0
        return -1;              /* need to be able to double it */
311
0
    if (size < 8)
312
0
        size = 8;               /* needed to behave well with flushing */
313
0
    state->want = size;
314
0
    return 0;
315
0
}
316
317
/* -- see zlib.h -- */
318
0
int ZEXPORT gzrewind(gzFile file) {
319
0
    gz_statep state;
320
321
    /* get internal structure */
322
0
    if (file == NULL)
323
0
        return -1;
324
0
    state = (gz_statep)file;
325
326
    /* check that we're reading and that there's no error */
327
0
    if (state->mode != GZ_READ ||
328
0
            (state->err != Z_OK && state->err != Z_BUF_ERROR))
329
0
        return -1;
330
331
    /* back up and start over */
332
0
    if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
333
0
        return -1;
334
0
    gz_reset(state);
335
0
    return 0;
336
0
}
337
338
/* -- see zlib.h -- */
339
0
z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) {
340
0
    unsigned n;
341
0
    z_off64_t ret;
342
0
    gz_statep state;
343
344
    /* get internal structure and check integrity */
345
0
    if (file == NULL)
346
0
        return -1;
347
0
    state = (gz_statep)file;
348
0
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
349
0
        return -1;
350
351
    /* check that there's no error */
352
0
    if (state->err != Z_OK && state->err != Z_BUF_ERROR)
353
0
        return -1;
354
355
    /* can only seek from start or relative to current position */
356
0
    if (whence != SEEK_SET && whence != SEEK_CUR)
357
0
        return -1;
358
359
    /* normalize offset to a SEEK_CUR specification */
360
0
    if (whence == SEEK_SET)
361
0
        offset -= state->x.pos;
362
0
    else if (state->seek)
363
0
        offset += state->skip;
364
0
    state->seek = 0;
365
366
    /* if within raw area while reading, just go there */
367
0
    if (state->mode == GZ_READ && state->how == COPY &&
368
0
            state->x.pos + offset >= 0) {
369
0
        ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR);
370
0
        if (ret == -1)
371
0
            return -1;
372
0
        state->x.have = 0;
373
0
        state->eof = 0;
374
0
        state->past = 0;
375
0
        state->seek = 0;
376
0
        gz_error(state, Z_OK, NULL);
377
0
        state->strm.avail_in = 0;
378
0
        state->x.pos += offset;
379
0
        return state->x.pos;
380
0
    }
381
382
    /* calculate skip amount, rewinding if needed for back seek when reading */
383
0
    if (offset < 0) {
384
0
        if (state->mode != GZ_READ)         /* writing -- can't go backwards */
385
0
            return -1;
386
0
        offset += state->x.pos;
387
0
        if (offset < 0)                     /* before start of file! */
388
0
            return -1;
389
0
        if (gzrewind(file) == -1)           /* rewind, then skip to offset */
390
0
            return -1;
391
0
    }
392
393
    /* if reading, skip what's in output buffer (one less gzgetc() check) */
394
0
    if (state->mode == GZ_READ) {
395
0
        n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
396
0
            (unsigned)offset : state->x.have;
397
0
        state->x.have -= n;
398
0
        state->x.next += n;
399
0
        state->x.pos += n;
400
0
        offset -= n;
401
0
    }
402
403
    /* request skip (if not zero) */
404
0
    if (offset) {
405
0
        state->seek = 1;
406
0
        state->skip = offset;
407
0
    }
408
0
    return state->x.pos + offset;
409
0
}
410
411
/* -- see zlib.h -- */
412
0
z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) {
413
0
    z_off64_t ret;
414
415
0
    ret = gzseek64(file, (z_off64_t)offset, whence);
416
0
    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
417
0
}
418
419
/* -- see zlib.h -- */
420
0
z_off64_t ZEXPORT gztell64(gzFile file) {
421
0
    gz_statep state;
422
423
    /* get internal structure and check integrity */
424
0
    if (file == NULL)
425
0
        return -1;
426
0
    state = (gz_statep)file;
427
0
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
428
0
        return -1;
429
430
    /* return position */
431
0
    return state->x.pos + (state->seek ? state->skip : 0);
432
0
}
433
434
/* -- see zlib.h -- */
435
0
z_off_t ZEXPORT gztell(gzFile file) {
436
0
    z_off64_t ret;
437
438
0
    ret = gztell64(file);
439
0
    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
440
0
}
441
442
/* -- see zlib.h -- */
443
0
z_off64_t ZEXPORT gzoffset64(gzFile file) {
444
0
    z_off64_t offset;
445
0
    gz_statep state;
446
447
    /* get internal structure and check integrity */
448
0
    if (file == NULL)
449
0
        return -1;
450
0
    state = (gz_statep)file;
451
0
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
452
0
        return -1;
453
454
    /* compute and return effective offset in file */
455
0
    offset = LSEEK(state->fd, 0, SEEK_CUR);
456
0
    if (offset == -1)
457
0
        return -1;
458
0
    if (state->mode == GZ_READ)             /* reading */
459
0
        offset -= state->strm.avail_in;     /* don't count buffered input */
460
0
    return offset;
461
0
}
462
463
/* -- see zlib.h -- */
464
0
z_off_t ZEXPORT gzoffset(gzFile file) {
465
0
    z_off64_t ret;
466
467
0
    ret = gzoffset64(file);
468
0
    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
469
0
}
470
471
/* -- see zlib.h -- */
472
0
int ZEXPORT gzeof(gzFile file) {
473
0
    gz_statep state;
474
475
    /* get internal structure and check integrity */
476
0
    if (file == NULL)
477
0
        return 0;
478
0
    state = (gz_statep)file;
479
0
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
480
0
        return 0;
481
482
    /* return end-of-file state */
483
0
    return state->mode == GZ_READ ? state->past : 0;
484
0
}
485
486
/* -- see zlib.h -- */
487
0
const char * ZEXPORT gzerror(gzFile file, int *errnum) {
488
0
    gz_statep state;
489
490
    /* get internal structure and check integrity */
491
0
    if (file == NULL)
492
0
        return NULL;
493
0
    state = (gz_statep)file;
494
0
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
495
0
        return NULL;
496
497
    /* return error information */
498
0
    if (errnum != NULL)
499
0
        *errnum = state->err;
500
0
    return state->err == Z_MEM_ERROR ? "out of memory" :
501
0
                                       (state->msg == NULL ? "" : state->msg);
502
0
}
503
504
/* -- see zlib.h -- */
505
0
void ZEXPORT gzclearerr(gzFile file) {
506
0
    gz_statep state;
507
508
    /* get internal structure and check integrity */
509
0
    if (file == NULL)
510
0
        return;
511
0
    state = (gz_statep)file;
512
0
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
513
0
        return;
514
515
    /* clear error and end-of-file */
516
0
    if (state->mode == GZ_READ) {
517
0
        state->eof = 0;
518
0
        state->past = 0;
519
0
    }
520
0
    gz_error(state, Z_OK, NULL);
521
0
}
522
523
/* Create an error message in allocated memory and set state->err and
524
   state->msg accordingly.  Free any previous error message already there.  Do
525
   not try to free or allocate space if the error is Z_MEM_ERROR (out of
526
   memory).  Simply save the error message as a static string.  If there is an
527
   allocation failure constructing the error message, then convert the error to
528
   out of memory. */
529
0
void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) {
530
    /* free previously allocated message and clear */
531
0
    if (state->msg != NULL) {
532
0
        if (state->err != Z_MEM_ERROR)
533
0
            free(state->msg);
534
0
        state->msg = NULL;
535
0
    }
536
537
    /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
538
0
    if (err != Z_OK && err != Z_BUF_ERROR)
539
0
        state->x.have = 0;
540
541
    /* set error code, and if no message, then done */
542
0
    state->err = err;
543
0
    if (msg == NULL)
544
0
        return;
545
546
    /* for an out of memory error, return literal string when requested */
547
0
    if (err == Z_MEM_ERROR)
548
0
        return;
549
550
    /* construct error message with path */
551
0
    if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
552
0
            NULL) {
553
0
        state->err = Z_MEM_ERROR;
554
0
        return;
555
0
    }
556
0
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
557
0
    (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
558
0
                   "%s%s%s", state->path, ": ", msg);
559
#else
560
    strcpy(state->msg, state->path);
561
    strcat(state->msg, ": ");
562
    strcat(state->msg, msg);
563
#endif
564
0
}
565
566
/* portably return maximum value for an int (when limits.h presumed not
567
   available) -- we need to do this to cover cases where 2's complement not
568
   used, since C standard permits 1's complement and sign-bit representations,
569
   otherwise we could just use ((unsigned)-1) >> 1 */
570
0
unsigned ZLIB_INTERNAL gz_intmax(void) {
571
0
#ifdef INT_MAX
572
0
    return INT_MAX;
573
#else
574
    unsigned p = 1, q;
575
    do {
576
        q = p;
577
        p <<= 1;
578
        p++;
579
    } while (p > q);
580
    return q >> 1;
581
#endif
582
0
}