aboutsummaryrefslogtreecommitdiff
path: root/gzread.c
diff options
context:
space:
mode:
authorMark Adler <madler@alumni.caltech.edu>2011-09-09 23:26:58 -0700
committerMark Adler <madler@alumni.caltech.edu>2011-09-09 23:26:58 -0700
commitdc5a43ebfadb6b775f6e64bfeb5a461c66acb394 (patch)
tree00e122ba59ad883db198dc6adf24d020cac924d3 /gzread.c
parentd004b047838a7e803818b4973a2e39e0ff8c1fa2 (diff)
downloadzlib-dc5a43ebfadb6b775f6e64bfeb5a461c66acb394.tar.gz
zlib-dc5a43ebfadb6b775f6e64bfeb5a461c66acb394.tar.bz2
zlib-dc5a43ebfadb6b775f6e64bfeb5a461c66acb394.zip
zlib 1.2.3.6v1.2.3.6
Diffstat (limited to 'gzread.c')
-rw-r--r--gzread.c48
1 files changed, 32 insertions, 16 deletions
diff --git a/gzread.c b/gzread.c
index 836c57c..74bdc7b 100644
--- a/gzread.c
+++ b/gzread.c
@@ -69,8 +69,8 @@ local int gz_avail(state)
69 (strm->avail_in == 0 ? -1 : \ 69 (strm->avail_in == 0 ? -1 : \
70 (strm->avail_in--, *(strm->next_in)++))) 70 (strm->avail_in--, *(strm->next_in)++)))
71 71
72/* Get a four-byte little-endian integer and return 0 on success and the 72/* Get a four-byte little-endian integer and return 0 on success and the value
73 value in *ret. Otherwise -1 is returned and *ret is not modified. */ 73 in *ret. Otherwise -1 is returned and *ret is not modified. */
74local int gz_next4(state, ret) 74local int gz_next4(state, ret)
75 gz_statep state; 75 gz_statep state;
76 unsigned long *ret; 76 unsigned long *ret;
@@ -93,7 +93,7 @@ local int gz_next4(state, ret)
93/* Look for gzip header, set up for inflate or copy. state->have must be zero. 93/* Look for gzip header, set up for inflate or copy. state->have must be zero.
94 If this is the first time in, allocate required memory. state->how will be 94 If this is the first time in, allocate required memory. state->how will be
95 left unchanged if there is no more input data available, will be set to 1 if 95 left unchanged if there is no more input data available, will be set to 1 if
96 there is no gzip header and direct copying will be performned, or it will be 96 there is no gzip header and direct copying will be performed, or it will be
97 set to 2 for decompression, and the gzip header will be skipped so that the 97 set to 2 for decompression, and the gzip header will be skipped so that the
98 next available input data is the raw deflate stream. If direct copying, 98 next available input data is the raw deflate stream. If direct copying,
99 then leftover input data from the input buffer will be copied to the output 99 then leftover input data from the input buffer will be copied to the output
@@ -190,6 +190,8 @@ local int gz_head(state)
190 NEXT(); 190 NEXT();
191 NEXT(); 191 NEXT();
192 } 192 }
193 /* an unexpected end of file is not checked for here -- it will be
194 noticed on the first request for uncompressed data */
193 195
194 /* set up for decompression */ 196 /* set up for decompression */
195 inflateReset(strm); 197 inflateReset(strm);
@@ -206,7 +208,7 @@ local int gz_head(state)
206 208
207 /* doing raw i/o, save start of raw data for seeking, copy any leftover 209 /* doing raw i/o, save start of raw data for seeking, copy any leftover
208 input to output -- this assumes that the output buffer is larger than 210 input to output -- this assumes that the output buffer is larger than
209 the input buffer */ 211 the input buffer, which also assures space for gzungetc() */
210 state->raw = state->pos; 212 state->raw = state->pos;
211 state->next = state->out; 213 state->next = state->out;
212 if (strm->avail_in) { 214 if (strm->avail_in) {
@@ -220,10 +222,10 @@ local int gz_head(state)
220 222
221/* Decompress from input to the provided next_out and avail_out in the state. 223/* Decompress from input to the provided next_out and avail_out in the state.
222 If the end of the compressed data is reached, then verify the gzip trailer 224 If the end of the compressed data is reached, then verify the gzip trailer
223 check value and length (modulo 2^32). state->have and state->next are 225 check value and length (modulo 2^32). state->have and state->next are set
224 set to point to the just decompressed data, and the crc is updated. If the 226 to point to the just decompressed data, and the crc is updated. If the
225 trailer is verified, state->how is reset to zero to look for the next gzip 227 trailer is verified, state->how is reset to zero to look for the next gzip
226 stream or raw data, once state->have is depleted. Returns 0 on success, -1 228 stream or raw data, once state->have is depleted. Returns 0 on success, -1
227 on failure. Failures may include invalid compressed data or a failed gzip 229 on failure. Failures may include invalid compressed data or a failed gzip
228 trailer verification. */ 230 trailer verification. */
229local int gz_decomp(state) 231local int gz_decomp(state)
@@ -372,6 +374,17 @@ int ZEXPORT gzread(file, buf, len)
372 if (state->mode != GZ_READ || state->err != Z_OK) 374 if (state->mode != GZ_READ || state->err != Z_OK)
373 return -1; 375 return -1;
374 376
377 /* since an int is returned, make sure len fits in one, otherwise return
378 with an error (this avoids the flaw in the interface) */
379 if ((int)len < 0) {
380 gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
381 return -1;
382 }
383
384 /* if len is zero, avoid unnecessary operations */
385 if (len == 0)
386 return 0;
387
375 /* process a skip request */ 388 /* process a skip request */
376 if (state->seek) { 389 if (state->seek) {
377 state->seek = 0; 390 state->seek = 0;
@@ -381,8 +394,7 @@ int ZEXPORT gzread(file, buf, len)
381 394
382 /* get len bytes to buf, or less than len if at the end */ 395 /* get len bytes to buf, or less than len if at the end */
383 got = 0; 396 got = 0;
384 while (len) { 397 do {
385
386 /* first just try copying data from the output buffer */ 398 /* first just try copying data from the output buffer */
387 if (state->have) { 399 if (state->have) {
388 n = state->have > len ? len : state->have; 400 n = state->have > len ? len : state->have;
@@ -402,6 +414,8 @@ int ZEXPORT gzread(file, buf, len)
402 if (gz_make(state) == -1) 414 if (gz_make(state) == -1)
403 return -1; 415 return -1;
404 continue; /* no progress yet -- go back to memcpy() above */ 416 continue; /* no progress yet -- go back to memcpy() above */
417 /* the copy above assures that we will leave with space in the
418 output buffer, allowing at least one gzungetc() to succeed */
405 } 419 }
406 420
407 /* large len -- read directly into user buffer */ 421 /* large len -- read directly into user buffer */
@@ -422,13 +436,13 @@ int ZEXPORT gzread(file, buf, len)
422 436
423 /* update progress */ 437 /* update progress */
424 len -= n; 438 len -= n;
425 buf += n; 439 buf = (char *)buf + n;
426 got += n; 440 got += n;
427 state->pos += n; 441 state->pos += n;
428 } 442 } while (len);
429 443
430 /* return number of bytes read into user buffer */ 444 /* return number of bytes read into user buffer (will fit in int) */
431 return (int)got; /* len had better fit in int -- interface flaw */ 445 return (int)got;
432} 446}
433 447
434/* -- see zlib.h -- */ 448/* -- see zlib.h -- */
@@ -448,7 +462,7 @@ int ZEXPORT gzgetc(file)
448 if (state->mode != GZ_READ || state->err != Z_OK) 462 if (state->mode != GZ_READ || state->err != Z_OK)
449 return -1; 463 return -1;
450 464
451 /* try output buffer */ 465 /* try output buffer (no need to check for skip request) */
452 if (state->have) { 466 if (state->have) {
453 state->have--; 467 state->have--;
454 state->pos++; 468 state->pos++;
@@ -496,9 +510,11 @@ int ZEXPORT gzungetc(c, file)
496 return c; 510 return c;
497 } 511 }
498 512
499 /* if no room, give up (must have already done a gz_ungetc()) */ 513 /* if no room, give up (must have already done a gzungetc()) */
500 if (state->have == (state->size << 1)) 514 if (state->have == (state->size << 1)) {
515 gz_error(state, Z_BUF_ERROR, "out of room to push characters");
501 return -1; 516 return -1;
517 }
502 518
503 /* slide output data if needed and insert byte before existing data */ 519 /* slide output data if needed and insert byte before existing data */
504 if (state->next == state->out) { 520 if (state->next == state->out) {