Coverage Report

Created: 2025-06-24 06:45

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