]> git.notmuchmail.org Git - apitrace/blob - thirdparty/zlib/gzread.c
Ignore unexpected end of file in gzread.
[apitrace] / thirdparty / zlib / gzread.c
1 /* gzread.c -- zlib functions for reading gzip files
2  * Copyright (C) 2004, 2005, 2010 Mark Adler
3  * For conditions of distribution and use, see copyright notice in zlib.h
4  */
5
6 #include "gzguts.h"
7
8 /* Local functions */
9 local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
10 local int gz_avail OF((gz_statep));
11 local int gz_next4 OF((gz_statep, unsigned long *));
12 local int gz_head OF((gz_statep));
13 local int gz_decomp OF((gz_statep));
14 local int gz_make OF((gz_statep));
15 local int gz_skip OF((gz_statep, z_off64_t));
16
17 /* Use read() to load a buffer -- return -1 on error, otherwise 0.  Read from
18    state->fd, and update state->eof, state->err, and state->msg as appropriate.
19    This function needs to loop on read(), since read() is not guaranteed to
20    read the number of bytes requested, depending on the type of descriptor. */
21 local int gz_load(state, buf, len, have)
22     gz_statep state;
23     unsigned char *buf;
24     unsigned len;
25     unsigned *have;
26 {
27     int ret;
28
29     *have = 0;
30     do {
31         ret = read(state->fd, buf + *have, len - *have);
32         if (ret <= 0)
33             break;
34         *have += ret;
35     } while (*have < len);
36     if (ret < 0) {
37         gz_error(state, Z_ERRNO, zstrerror());
38         return -1;
39     }
40     if (ret == 0)
41         state->eof = 1;
42     return 0;
43 }
44
45 /* Load up input buffer and set eof flag if last data loaded -- return -1 on
46    error, 0 otherwise.  Note that the eof flag is set when the end of the input
47    file is reached, even though there may be unused data in the buffer.  Once
48    that data has been used, no more attempts will be made to read the file.
49    gz_avail() assumes that strm->avail_in == 0. */
50 local int gz_avail(state)
51     gz_statep state;
52 {
53     z_streamp strm = &(state->strm);
54
55     if (state->err != Z_OK)
56         return -1;
57     if (state->eof == 0) {
58         if (gz_load(state, state->in, state->size,
59                 (unsigned *)&(strm->avail_in)) == -1)
60             return -1;
61         strm->next_in = state->in;
62     }
63     return 0;
64 }
65
66 /* Get next byte from input, or -1 if end or error. */
67 #define NEXT() ((strm->avail_in == 0 && gz_avail(state) == -1) ? -1 : \
68                 (strm->avail_in == 0 ? -1 : \
69                  (strm->avail_in--, *(strm->next_in)++)))
70
71 /* Get a four-byte little-endian integer and return 0 on success and the value
72    in *ret.  Otherwise -1 is returned and *ret is not modified. */
73 local int gz_next4(state, ret)
74     gz_statep state;
75     unsigned long *ret;
76 {
77     int ch;
78     unsigned long val;
79     z_streamp strm = &(state->strm);
80
81     val = NEXT();
82     val += (unsigned)NEXT() << 8;
83     val += (unsigned long)NEXT() << 16;
84     ch = NEXT();
85     if (ch == -1)
86         return -1;
87     val += (unsigned long)ch << 24;
88     *ret = val;
89     return 0;
90 }
91
92 /* Look for gzip header, set up for inflate or copy.  state->have must be zero.
93    If this is the first time in, allocate required memory.  state->how will be
94    left unchanged if there is no more input data available, will be set to COPY
95    if there is no gzip header and direct copying will be performed, or it will
96    be set to GZIP for decompression, and the gzip header will be skipped so
97    that the next available input data is the raw deflate stream.  If direct
98    copying, then leftover input data from the input buffer will be copied to
99    the output buffer.  In that case, all further file reads will be directly to
100    either the output buffer or a user buffer.  If decompressing, the inflate
101    state and the check value will be initialized.  gz_head() will return 0 on
102    success or -1 on failure.  Failures may include read errors or gzip header
103    errors.  */
104 local int gz_head(state)
105     gz_statep state;
106 {
107     z_streamp strm = &(state->strm);
108     int flags;
109     unsigned len;
110
111     /* allocate read buffers and inflate memory */
112     if (state->size == 0) {
113         /* allocate buffers */
114         state->in = malloc(state->want);
115         state->out = malloc(state->want << 1);
116         if (state->in == NULL || state->out == NULL) {
117             if (state->out != NULL)
118                 free(state->out);
119             if (state->in != NULL)
120                 free(state->in);
121             gz_error(state, Z_MEM_ERROR, "out of memory");
122             return -1;
123         }
124         state->size = state->want;
125
126         /* allocate inflate memory */
127         state->strm.zalloc = Z_NULL;
128         state->strm.zfree = Z_NULL;
129         state->strm.opaque = Z_NULL;
130         state->strm.avail_in = 0;
131         state->strm.next_in = Z_NULL;
132         if (inflateInit2(&(state->strm), -15) != Z_OK) {    /* raw inflate */
133             free(state->out);
134             free(state->in);
135             state->size = 0;
136             gz_error(state, Z_MEM_ERROR, "out of memory");
137             return -1;
138         }
139     }
140
141     /* get some data in the input buffer */
142     if (strm->avail_in == 0) {
143         if (gz_avail(state) == -1)
144             return -1;
145         if (strm->avail_in == 0)
146             return 0;
147     }
148
149     /* look for the gzip magic header bytes 31 and 139 */
150     if (strm->next_in[0] == 31) {
151         strm->avail_in--;
152         strm->next_in++;
153         if (strm->avail_in == 0 && gz_avail(state) == -1)
154             return -1;
155         if (strm->avail_in && strm->next_in[0] == 139) {
156             /* we have a gzip header, woo hoo! */
157             strm->avail_in--;
158             strm->next_in++;
159
160             /* skip rest of header */
161             if (NEXT() != 8) {      /* compression method */
162                 gz_error(state, Z_DATA_ERROR, "unknown compression method");
163                 return -1;
164             }
165             flags = NEXT();
166             if (flags & 0xe0) {     /* reserved flag bits */
167                 gz_error(state, Z_DATA_ERROR, "unknown header flags set");
168                 return -1;
169             }
170             NEXT();                 /* modification time */
171             NEXT();
172             NEXT();
173             NEXT();
174             NEXT();                 /* extra flags */
175             NEXT();                 /* operating system */
176             if (flags & 4) {        /* extra field */
177                 len = (unsigned)NEXT();
178                 len += (unsigned)NEXT() << 8;
179                 while (len--)
180                     if (NEXT() < 0)
181                         break;
182             }
183             if (flags & 8)          /* file name */
184                 while (NEXT() > 0)
185                     ;
186             if (flags & 16)         /* comment */
187                 while (NEXT() > 0)
188                     ;
189             if (flags & 2) {        /* header crc */
190                 NEXT();
191                 NEXT();
192             }
193             /* an unexpected end of file is not checked for here -- it will be
194                noticed on the first request for uncompressed data */
195
196             /* set up for decompression */
197             inflateReset(strm);
198             strm->adler = crc32(0L, Z_NULL, 0);
199             state->how = GZIP;
200             state->direct = 0;
201             return 0;
202         }
203         else {
204             /* not a gzip file -- save first byte (31) and fall to raw i/o */
205             state->out[0] = 31;
206             state->have = 1;
207         }
208     }
209
210     /* doing raw i/o, save start of raw data for seeking, copy any leftover
211        input to output -- this assumes that the output buffer is larger than
212        the input buffer, which also assures space for gzungetc() */
213     state->raw = state->pos;
214     state->next = state->out;
215     if (strm->avail_in) {
216         memcpy(state->next + state->have, strm->next_in, strm->avail_in);
217         state->have += strm->avail_in;
218         strm->avail_in = 0;
219     }
220     state->how = COPY;
221     state->direct = 1;
222     return 0;
223 }
224
225 /* Decompress from input to the provided next_out and avail_out in the state.
226    If the end of the compressed data is reached, then verify the gzip trailer
227    check value and length (modulo 2^32).  state->have and state->next are set
228    to point to the just decompressed data, and the crc is updated.  If the
229    trailer is verified, state->how is reset to LOOK to look for the next gzip
230    stream or raw data, once state->have is depleted.  Returns 0 on success, -1
231    on failure.  Failures may include invalid compressed data or a failed gzip
232    trailer verification. */
233 local int gz_decomp(state)
234     gz_statep state;
235 {
236     int ret;
237     unsigned had;
238     unsigned long crc, len;
239     z_streamp strm = &(state->strm);
240
241     /* fill output buffer up to end of deflate stream */
242     had = strm->avail_out;
243     do {
244         /* get more input for inflate() */
245         if (strm->avail_in == 0 && gz_avail(state) == -1)
246             return -1;
247         if (strm->avail_in == 0) {
248 #if 0
249             gz_error(state, Z_DATA_ERROR, "unexpected end of file");
250             return -1;
251 #else
252             /* APITRACE: Ignore unexpected end of file. */
253             ret = 0;
254             break;
255 #endif
256         }
257
258         /* decompress and handle errors */
259         ret = inflate(strm, Z_NO_FLUSH);
260         if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
261             gz_error(state, Z_STREAM_ERROR,
262                       "internal error: inflate stream corrupt");
263             return -1;
264         }
265         if (ret == Z_MEM_ERROR) {
266             gz_error(state, Z_MEM_ERROR, "out of memory");
267             return -1;
268         }
269         if (ret == Z_DATA_ERROR) {              /* deflate stream invalid */
270             gz_error(state, Z_DATA_ERROR,
271                       strm->msg == NULL ? "compressed data error" : strm->msg);
272             return -1;
273         }
274     } while (strm->avail_out && ret != Z_STREAM_END);
275
276     /* update available output and crc check value */
277     state->have = had - strm->avail_out;
278     state->next = strm->next_out - state->have;
279     strm->adler = crc32(strm->adler, state->next, state->have);
280
281     /* check gzip trailer if at end of deflate stream */
282     if (ret == Z_STREAM_END) {
283         if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) {
284             gz_error(state, Z_DATA_ERROR, "unexpected end of file");
285             return -1;
286         }
287         if (crc != strm->adler) {
288             gz_error(state, Z_DATA_ERROR, "incorrect data check");
289             return -1;
290         }
291         if (len != (strm->total_out & 0xffffffffL)) {
292             gz_error(state, Z_DATA_ERROR, "incorrect length check");
293             return -1;
294         }
295         state->how = LOOK;      /* ready for next stream, once have is 0 (leave
296                                    state->direct unchanged to remember how) */
297     }
298
299     /* good decompression */
300     return 0;
301 }
302
303 /* Make data and put in the output buffer.  Assumes that state->have == 0.
304    Data is either copied from the input file or decompressed from the input
305    file depending on state->how.  If state->how is LOOK, then a gzip header is
306    looked for (and skipped if found) to determine wither to copy or decompress.
307    Returns -1 on error, otherwise 0.  gz_make() will leave state->have as COPY
308    or GZIP unless the end of the input file has been reached and all data has
309    been processed.  */
310 local int gz_make(state)
311     gz_statep state;
312 {
313     z_streamp strm = &(state->strm);
314
315     if (state->how == LOOK) {           /* look for gzip header */
316         if (gz_head(state) == -1)
317             return -1;
318         if (state->have)                /* got some data from gz_head() */
319             return 0;
320     }
321     if (state->how == COPY) {           /* straight copy */
322         if (gz_load(state, state->out, state->size << 1, &(state->have)) == -1)
323             return -1;
324         state->next = state->out;
325     }
326     else if (state->how == GZIP) {      /* decompress */
327         strm->avail_out = state->size << 1;
328         strm->next_out = state->out;
329         if (gz_decomp(state) == -1)
330             return -1;
331     }
332     return 0;
333 }
334
335 /* Skip len uncompressed bytes of output.  Return -1 on error, 0 on success. */
336 local int gz_skip(state, len)
337     gz_statep state;
338     z_off64_t len;
339 {
340     unsigned n;
341
342     /* skip over len bytes or reach end-of-file, whichever comes first */
343     while (len)
344         /* skip over whatever is in output buffer */
345         if (state->have) {
346             n = GT_OFF(state->have) || (z_off64_t)state->have > len ?
347                 (unsigned)len : state->have;
348             state->have -= n;
349             state->next += n;
350             state->pos += n;
351             len -= n;
352         }
353
354         /* output buffer empty -- return if we're at the end of the input */
355         else if (state->eof && state->strm.avail_in == 0)
356             break;
357
358         /* need more data to skip -- load up output buffer */
359         else {
360             /* get more output, looking for header if required */
361             if (gz_make(state) == -1)
362                 return -1;
363         }
364     return 0;
365 }
366
367 /* -- see zlib.h -- */
368 int ZEXPORT gzread(file, buf, len)
369     gzFile file;
370     voidp buf;
371     unsigned len;
372 {
373     unsigned got, n;
374     gz_statep state;
375     z_streamp strm;
376
377     /* get internal structure */
378     if (file == NULL)
379         return -1;
380     state = (gz_statep)file;
381     strm = &(state->strm);
382
383     /* check that we're reading and that there's no error */
384     if (state->mode != GZ_READ || state->err != Z_OK)
385         return -1;
386
387     /* since an int is returned, make sure len fits in one, otherwise return
388        with an error (this avoids the flaw in the interface) */
389     if ((int)len < 0) {
390         gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
391         return -1;
392     }
393
394     /* if len is zero, avoid unnecessary operations */
395     if (len == 0)
396         return 0;
397
398     /* process a skip request */
399     if (state->seek) {
400         state->seek = 0;
401         if (gz_skip(state, state->skip) == -1)
402             return -1;
403     }
404
405     /* get len bytes to buf, or less than len if at the end */
406     got = 0;
407     do {
408         /* first just try copying data from the output buffer */
409         if (state->have) {
410             n = state->have > len ? len : state->have;
411             memcpy(buf, state->next, n);
412             state->next += n;
413             state->have -= n;
414         }
415
416         /* output buffer empty -- return if we're at the end of the input */
417         else if (state->eof && strm->avail_in == 0)
418             break;
419
420         /* need output data -- for small len or new stream load up our output
421            buffer */
422         else if (state->how == LOOK || len < (state->size << 1)) {
423             /* get more output, looking for header if required */
424             if (gz_make(state) == -1)
425                 return -1;
426             continue;       /* no progress yet -- go back to memcpy() above */
427             /* the copy above assures that we will leave with space in the
428                output buffer, allowing at least one gzungetc() to succeed */
429         }
430
431         /* large len -- read directly into user buffer */
432         else if (state->how == COPY) {      /* read directly */
433             if (gz_load(state, buf, len, &n) == -1)
434                 return -1;
435         }
436
437         /* large len -- decompress directly into user buffer */
438         else {  /* state->how == GZIP */
439             strm->avail_out = len;
440             strm->next_out = buf;
441             if (gz_decomp(state) == -1)
442                 return -1;
443             n = state->have;
444             state->have = 0;
445         }
446
447         /* update progress */
448         len -= n;
449         buf = (char *)buf + n;
450         got += n;
451         state->pos += n;
452     } while (len);
453
454     /* return number of bytes read into user buffer (will fit in int) */
455     return (int)got;
456 }
457
458 /* -- see zlib.h -- */
459 int ZEXPORT gzgetc(file)
460     gzFile file;
461 {
462     int ret;
463     unsigned char buf[1];
464     gz_statep state;
465
466     /* get internal structure */
467     if (file == NULL)
468         return -1;
469     state = (gz_statep)file;
470
471     /* check that we're reading and that there's no error */
472     if (state->mode != GZ_READ || state->err != Z_OK)
473         return -1;
474
475     /* try output buffer (no need to check for skip request) */
476     if (state->have) {
477         state->have--;
478         state->pos++;
479         return *(state->next)++;
480     }
481
482     /* nothing there -- try gzread() */
483     ret = gzread(file, buf, 1);
484     return ret < 1 ? -1 : buf[0];
485 }
486
487 /* -- see zlib.h -- */
488 int ZEXPORT gzungetc(c, file)
489     int c;
490     gzFile file;
491 {
492     gz_statep state;
493
494     /* get internal structure */
495     if (file == NULL)
496         return -1;
497     state = (gz_statep)file;
498
499     /* check that we're reading and that there's no error */
500     if (state->mode != GZ_READ || state->err != Z_OK)
501         return -1;
502
503     /* process a skip request */
504     if (state->seek) {
505         state->seek = 0;
506         if (gz_skip(state, state->skip) == -1)
507             return -1;
508     }
509
510     /* can't push EOF */
511     if (c < 0)
512         return -1;
513
514     /* if output buffer empty, put byte at end (allows more pushing) */
515     if (state->have == 0) {
516         state->have = 1;
517         state->next = state->out + (state->size << 1) - 1;
518         state->next[0] = c;
519         state->pos--;
520         return c;
521     }
522
523     /* if no room, give up (must have already done a gzungetc()) */
524     if (state->have == (state->size << 1)) {
525         gz_error(state, Z_BUF_ERROR, "out of room to push characters");
526         return -1;
527     }
528
529     /* slide output data if needed and insert byte before existing data */
530     if (state->next == state->out) {
531         unsigned char *src = state->out + state->have;
532         unsigned char *dest = state->out + (state->size << 1);
533         while (src > state->out)
534             *--dest = *--src;
535         state->next = dest;
536     }
537     state->have++;
538     state->next--;
539     state->next[0] = c;
540     state->pos--;
541     return c;
542 }
543
544 /* -- see zlib.h -- */
545 char * ZEXPORT gzgets(file, buf, len)
546     gzFile file;
547     char *buf;
548     int len;
549 {
550     unsigned left, n;
551     char *str;
552     unsigned char *eol;
553     gz_statep state;
554
555     /* check parameters and get internal structure */
556     if (file == NULL || buf == NULL || len < 1)
557         return NULL;
558     state = (gz_statep)file;
559
560     /* check that we're reading and that there's no error */
561     if (state->mode != GZ_READ || state->err != Z_OK)
562         return NULL;
563
564     /* process a skip request */
565     if (state->seek) {
566         state->seek = 0;
567         if (gz_skip(state, state->skip) == -1)
568             return NULL;
569     }
570
571     /* copy output bytes up to new line or len - 1, whichever comes first --
572        append a terminating zero to the string (we don't check for a zero in
573        the contents, let the user worry about that) */
574     str = buf;
575     left = (unsigned)len - 1;
576     if (left) do {
577         /* assure that something is in the output buffer */
578         if (state->have == 0) {
579             if (gz_make(state) == -1)
580                 return NULL;            /* error */
581             if (state->have == 0) {     /* end of file */
582                 if (buf == str)         /* got bupkus */
583                     return NULL;
584                 break;                  /* got something -- return it */
585             }
586         }
587
588         /* look for end-of-line in current output buffer */
589         n = state->have > left ? left : state->have;
590         eol = memchr(state->next, '\n', n);
591         if (eol != NULL)
592             n = (unsigned)(eol - state->next) + 1;
593
594         /* copy through end-of-line, or remainder if not found */
595         memcpy(buf, state->next, n);
596         state->have -= n;
597         state->next += n;
598         state->pos += n;
599         left -= n;
600         buf += n;
601     } while (left && eol == NULL);
602
603     /* found end-of-line or out of space -- terminate string and return it */
604     buf[0] = 0;
605     return str;
606 }
607
608 /* -- see zlib.h -- */
609 int ZEXPORT gzdirect(file)
610     gzFile file;
611 {
612     gz_statep state;
613
614     /* get internal structure */
615     if (file == NULL)
616         return 0;
617     state = (gz_statep)file;
618
619     /* check that we're reading */
620     if (state->mode != GZ_READ)
621         return 0;
622
623     /* if the state is not known, but we can find out, then do so (this is
624        mainly for right after a gzopen() or gzdopen()) */
625     if (state->how == LOOK && state->have == 0)
626         (void)gz_head(state);
627
628     /* return 1 if reading direct, 0 if decompressing a gzip stream */
629     return state->direct;
630 }
631
632 /* -- see zlib.h -- */
633 int ZEXPORT gzclose_r(file)
634     gzFile file;
635 {
636     int ret;
637     gz_statep state;
638
639     /* get internal structure */
640     if (file == NULL)
641         return Z_STREAM_ERROR;
642     state = (gz_statep)file;
643
644     /* check that we're reading */
645     if (state->mode != GZ_READ)
646         return Z_STREAM_ERROR;
647
648     /* free memory and close file */
649     if (state->size) {
650         inflateEnd(&(state->strm));
651         free(state->out);
652         free(state->in);
653     }
654     gz_error(state, Z_OK, NULL);
655     free(state->path);
656     ret = close(state->fd);
657     free(state);
658     return ret ? Z_ERRNO : Z_OK;
659 }