Index: third_party/zlib/gzread.c |
diff --git a/third_party/zlib/gzread.c b/third_party/zlib/gzread.c |
index 4e11246d8756a1c36ca8e59c3202f64bc4f2d505..832d3ef98c594827b31f47f9a41311b21a88151a 100644 |
--- a/third_party/zlib/gzread.c |
+++ b/third_party/zlib/gzread.c |
@@ -1,5 +1,5 @@ |
/* gzread.c -- zlib functions for reading gzip files |
- * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler |
+ * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler |
* For conditions of distribution and use, see copyright notice in zlib.h |
*/ |
@@ -12,6 +12,7 @@ local int gz_look OF((gz_statep)); |
local int gz_decomp OF((gz_statep)); |
local int gz_fetch OF((gz_statep)); |
local int gz_skip OF((gz_statep, z_off64_t)); |
+local z_size_t gz_read OF((gz_statep, voidp, z_size_t)); |
/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from |
state->fd, and update state->eof, state->err, and state->msg as appropriate. |
@@ -24,13 +25,17 @@ local int gz_load(state, buf, len, have) |
unsigned *have; |
{ |
int ret; |
+ unsigned get, max = ((unsigned)-1 >> 2) + 1; |
*have = 0; |
do { |
- ret = read(state->fd, buf + *have, len - *have); |
+ get = len - *have; |
+ if (get > max) |
+ get = max; |
+ ret = read(state->fd, buf + *have, get); |
if (ret <= 0) |
break; |
- *have += ret; |
+ *have += (unsigned)ret; |
} while (*have < len); |
if (ret < 0) { |
gz_error(state, Z_ERRNO, zstrerror()); |
@@ -94,10 +99,8 @@ local int gz_look(state) |
state->in = (unsigned char *)malloc(state->want); |
state->out = (unsigned char *)malloc(state->want << 1); |
if (state->in == NULL || state->out == NULL) { |
- if (state->out != NULL) |
- free(state->out); |
- if (state->in != NULL) |
- free(state->in); |
+ free(state->out); |
+ free(state->in); |
gz_error(state, Z_MEM_ERROR, "out of memory"); |
return -1; |
} |
@@ -284,33 +287,17 @@ local int gz_skip(state, len) |
return 0; |
} |
-/* -- see zlib.h -- */ |
-int ZEXPORT gzread(file, buf, len) |
- gzFile file; |
+/* Read len bytes into buf from file, or less than len up to the end of the |
+ input. Return the number of bytes read. If zero is returned, either the |
+ end of file was reached, or there was an error. state->err must be |
+ consulted in that case to determine which. */ |
+local z_size_t gz_read(state, buf, len) |
+ gz_statep state; |
voidp buf; |
- unsigned len; |
+ z_size_t len; |
{ |
- unsigned got, n; |
- gz_statep state; |
- z_streamp strm; |
- |
- /* get internal structure */ |
- if (file == NULL) |
- return -1; |
- state = (gz_statep)file; |
- strm = &(state->strm); |
- |
- /* check that we're reading and that there's no (serious) error */ |
- if (state->mode != GZ_READ || |
- (state->err != Z_OK && state->err != Z_BUF_ERROR)) |
- return -1; |
- |
- /* since an int is returned, make sure len fits in one, otherwise return |
- with an error (this avoids the flaw in the interface) */ |
- if ((int)len < 0) { |
- gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); |
- return -1; |
- } |
+ z_size_t got; |
+ unsigned n; |
/* if len is zero, avoid unnecessary operations */ |
if (len == 0) |
@@ -320,32 +307,38 @@ int ZEXPORT gzread(file, buf, len) |
if (state->seek) { |
state->seek = 0; |
if (gz_skip(state, state->skip) == -1) |
- return -1; |
+ return 0; |
} |
/* get len bytes to buf, or less than len if at the end */ |
got = 0; |
do { |
+ /* set n to the maximum amount of len that fits in an unsigned int */ |
+ n = -1; |
+ if (n > len) |
+ n = len; |
+ |
/* first just try copying data from the output buffer */ |
if (state->x.have) { |
- n = state->x.have > len ? len : state->x.have; |
+ if (state->x.have < n) |
+ n = state->x.have; |
memcpy(buf, state->x.next, n); |
state->x.next += n; |
state->x.have -= n; |
} |
/* output buffer empty -- return if we're at the end of the input */ |
- else if (state->eof && strm->avail_in == 0) { |
+ else if (state->eof && state->strm.avail_in == 0) { |
state->past = 1; /* tried to read past end */ |
break; |
} |
/* need output data -- for small len or new stream load up our output |
buffer */ |
- else if (state->how == LOOK || len < (state->size << 1)) { |
+ else if (state->how == LOOK || n < (state->size << 1)) { |
/* get more output, looking for header if required */ |
if (gz_fetch(state) == -1) |
- return -1; |
+ return 0; |
continue; /* no progress yet -- go back to copy above */ |
/* the copy above assures that we will leave with space in the |
output buffer, allowing at least one gzungetc() to succeed */ |
@@ -353,16 +346,16 @@ int ZEXPORT gzread(file, buf, len) |
/* large len -- read directly into user buffer */ |
else if (state->how == COPY) { /* read directly */ |
- if (gz_load(state, (unsigned char *)buf, len, &n) == -1) |
- return -1; |
+ if (gz_load(state, (unsigned char *)buf, n, &n) == -1) |
+ return 0; |
} |
/* large len -- decompress directly into user buffer */ |
else { /* state->how == GZIP */ |
- strm->avail_out = len; |
- strm->next_out = (unsigned char *)buf; |
+ state->strm.avail_out = n; |
+ state->strm.next_out = (unsigned char *)buf; |
if (gz_decomp(state) == -1) |
- return -1; |
+ return 0; |
n = state->x.have; |
state->x.have = 0; |
} |
@@ -374,8 +367,75 @@ int ZEXPORT gzread(file, buf, len) |
state->x.pos += n; |
} while (len); |
- /* return number of bytes read into user buffer (will fit in int) */ |
- return (int)got; |
+ /* return number of bytes read into user buffer */ |
+ return got; |
+} |
+ |
+/* -- see zlib.h -- */ |
+int ZEXPORT gzread(file, buf, len) |
+ gzFile file; |
+ voidp buf; |
+ unsigned len; |
+{ |
+ gz_statep state; |
+ |
+ /* get internal structure */ |
+ if (file == NULL) |
+ return -1; |
+ state = (gz_statep)file; |
+ |
+ /* check that we're reading and that there's no (serious) error */ |
+ if (state->mode != GZ_READ || |
+ (state->err != Z_OK && state->err != Z_BUF_ERROR)) |
+ return -1; |
+ |
+ /* since an int is returned, make sure len fits in one, otherwise return |
+ with an error (this avoids a flaw in the interface) */ |
+ if ((int)len < 0) { |
+ gz_error(state, Z_STREAM_ERROR, "request does not fit in an int"); |
+ return -1; |
+ } |
+ |
+ /* read len or fewer bytes to buf */ |
+ len = gz_read(state, buf, len); |
+ |
+ /* check for an error */ |
+ if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR) |
+ return -1; |
+ |
+ /* return the number of bytes read (this is assured to fit in an int) */ |
+ return (int)len; |
+} |
+ |
+/* -- see zlib.h -- */ |
+z_size_t ZEXPORT gzfread(buf, size, nitems, file) |
+ voidp buf; |
+ z_size_t size; |
+ z_size_t nitems; |
+ gzFile file; |
+{ |
+ z_size_t len; |
+ gz_statep state; |
+ |
+ /* get internal structure */ |
+ if (file == NULL) |
+ return 0; |
+ state = (gz_statep)file; |
+ |
+ /* check that we're reading and that there's no (serious) error */ |
+ if (state->mode != GZ_READ || |
+ (state->err != Z_OK && state->err != Z_BUF_ERROR)) |
+ return 0; |
+ |
+ /* compute bytes to read -- error on overflow */ |
+ len = nitems * size; |
+ if (size && len / size != nitems) { |
+ gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); |
+ return 0; |
+ } |
+ |
+ /* read len or fewer bytes to buf, return the number of full items read */ |
+ return len ? gz_read(state, buf, len) / size : 0; |
} |
/* -- see zlib.h -- */ |
@@ -383,8 +443,8 @@ int ZEXPORT gzread(file, buf, len) |
# undef z_gzgetc |
#else |
# undef gzgetc |
-# ifdef MOZZCONF_H |
-# define gzgetc MOZ_Z_gzgetc |
+# ifdef Z_CR_PREFIX_SET |
+# define gzgetc Cr_z_gzgetc |
# endif |
#endif |
@@ -412,8 +472,8 @@ int ZEXPORT gzgetc(file) |
return *(state->x.next)++; |
} |
- /* nothing there -- try gzread() */ |
- ret = gzread(file, buf, 1); |
+ /* nothing there -- try gz_read() */ |
+ ret = gz_read(state, buf, 1); |
return ret < 1 ? -1 : buf[0]; |
} |
@@ -455,7 +515,7 @@ int ZEXPORT gzungetc(c, file) |
if (state->x.have == 0) { |
state->x.have = 1; |
state->x.next = state->out + (state->size << 1) - 1; |
- state->x.next[0] = c; |
+ state->x.next[0] = (unsigned char)c; |
state->x.pos--; |
state->past = 0; |
return c; |
@@ -477,7 +537,7 @@ int ZEXPORT gzungetc(c, file) |
} |
state->x.have++; |
state->x.next--; |
- state->x.next[0] = c; |
+ state->x.next[0] = (unsigned char)c; |
state->x.pos--; |
state->past = 0; |
return c; |