/* longjmp */
jmp_buf gzlog_jump; /* where to go back to */
int gzlog_bail = 0; /* which point to bail at (1..8) */
@@ -756,12 +756,14 @@ local int log_recover(struct log *log, int op)
return -2;
}
if ((fd = open(log->path, O_RDONLY, 0)) < 0) {
+ free(data);
log_log(log, op, ".add file read failure");
return -1;
}
ret = (size_t)read(fd, data, len) != len;
close(fd);
if (ret) {
+ free(data);
log_log(log, op, ".add file read failure");
return -1;
}
diff --git a/zlib/examples/gzlog.h b/zlib/examples/gzlog.h
index 86f0cecba..4f0510955 100644
--- a/zlib/examples/gzlog.h
+++ b/zlib/examples/gzlog.h
@@ -40,7 +40,7 @@
its new size at that time. After each write operation, the log file is a
valid gzip file that can decompressed to recover what was written.
- The gzlog operations can be interupted at any point due to an application or
+ The gzlog operations can be interrupted at any point due to an application or
system crash, and the log file will be recovered the next time the log is
opened with gzlog_open().
*/
diff --git a/zlib/examples/zlib_how.html b/zlib/examples/zlib_how.html
index 444ff1c9a..59af43e25 100644
--- a/zlib/examples/zlib_how.html
+++ b/zlib/examples/zlib_how.html
@@ -1,10 +1,10 @@
-
+
zlib Usage Example
-
+
zlib Usage Example
@@ -17,11 +17,11 @@ zlib Usage Example
annotations are interspersed between lines of the code. So please read between the lines.
We hope this helps explain some of the intricacies of zlib.
-Without further adieu, here is the program zpipe.c:
+Without further ado, here is the program zpipe.c:
/* zpipe.c: example of proper use of zlib's inflate() and deflate()
Not copyrighted -- provided to the public domain
- Version 1.4 11 December 2005 Mark Adler */
+ Version 1.5 11 February 2026 Mark Adler */
/* Version history:
1.0 30 Oct 2004 First version
@@ -31,6 +31,7 @@ zlib Usage Example
1.3 6 Apr 2005 Remove incorrect assertion in inf()
1.4 11 Dec 2005 Add hack to avoid MSDOS end-of-line conversions
Avoid some compiler warnings for input and output buffers
+ 1.5 11 Feb 2026 Use underscores for Windows POSIX names
*/
We now include the header files for the required definitions. From
@@ -60,7 +61,7 @@ zlib Usage Example
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
# include <fcntl.h>
# include <io.h>
-# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+# define SET_BINARY_MODE(file) _setmode(_fileno(file), _O_BINARY)
#else
# define SET_BINARY_MODE(file)
#endif
@@ -155,13 +156,11 @@ zlib Usage Example
We start off by reading data from the input file. The number of bytes read is put directly
into avail_in, and a pointer to those bytes is put into next_in. We also
-check to see if end-of-file on the input has been reached. If we are at the end of file, then flush is set to the
+check to see if end-of-file on the input has been reached using feof().
+If we are at the end of file, then flush is set to the
zlib constant Z_FINISH, which is later passed to deflate() to
-indicate that this is the last chunk of input data to compress. We need to use feof()
-to check for end-of-file as opposed to seeing if fewer than CHUNK bytes have been read. The
-reason is that if the input file length is an exact multiple of CHUNK, we will miss
-the fact that we got to the end-of-file, and not know to tell deflate() to finish
-up the compressed stream. If we are not yet at the end of the input, then the zlib
+indicate that this is the last chunk of input data to compress.
+If we are not yet at the end of the input, then the zlib
constant Z_NO_FLUSH will be passed to deflate to indicate that we are still
in the middle of the uncompressed data.
@@ -540,6 +539,12 @@
zlib Usage Example
}
-Copyright (c) 2004, 2005 by Mark Adler
Last modified 11 December 2005
+Last modified 12 February 2026
+Copyright © 2004-2026 Mark Adler
+
+
+
+Creative Commons Attribution-NoDerivatives 4.0 International License.
diff --git a/zlib/examples/zpipe.c b/zlib/examples/zpipe.c
index 83535d169..021c85089 100644
--- a/zlib/examples/zpipe.c
+++ b/zlib/examples/zpipe.c
@@ -1,6 +1,6 @@
/* zpipe.c: example of proper use of zlib's inflate() and deflate()
Not copyrighted -- provided to the public domain
- Version 1.4 11 December 2005 Mark Adler */
+ Version 1.5 11 February 2026 Mark Adler */
/* Version history:
1.0 30 Oct 2004 First version
@@ -10,6 +10,7 @@
1.3 6 Apr 2005 Remove incorrect assertion in inf()
1.4 11 Dec 2005 Add hack to avoid MSDOS end-of-line conversions
Avoid some compiler warnings for input and output buffers
+ 1.5 11 Feb 2026 Use underscores for Windows POSIX names
*/
#include
@@ -20,7 +21,7 @@
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
# include
# include
-# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+# define SET_BINARY_MODE(file) _setmode(_fileno(file), _O_BINARY)
#else
# define SET_BINARY_MODE(file)
#endif
diff --git a/zlib/examples/zran.c b/zlib/examples/zran.c
index 278f9ad07..731d34d67 100644
--- a/zlib/examples/zran.c
+++ b/zlib/examples/zran.c
@@ -1,383 +1,516 @@
-/* zran.c -- example of zlib/gzip stream indexing and random access
- * Copyright (C) 2005, 2012 Mark Adler
+/* zran.c -- example of deflate stream indexing and random access
+ * Copyright (C) 2005, 2012, 2018, 2023, 2024, 2025 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
- Version 1.1 29 Sep 2012 Mark Adler */
+ * Version 1.7 16 May 2025 Mark Adler */
/* Version History:
1.0 29 May 2005 First version
1.1 29 Sep 2012 Fix memory reallocation error
+ 1.2 14 Oct 2018 Handle gzip streams with multiple members
+ Add a header file to facilitate usage in applications
+ 1.3 18 Feb 2023 Permit raw deflate streams as well as zlib and gzip
+ Permit crossing gzip member boundaries when extracting
+ Support a size_t size when extracting (was an int)
+ Do a binary search over the index for an access point
+ Expose the access point type to enable save and load
+ 1.4 13 Apr 2023 Add a NOPRIME define to not use inflatePrime()
+ 1.5 4 Feb 2024 Set returned index to NULL on an index build error
+ Stop decoding once request is satisfied
+ Provide a reusable inflate engine in the index
+ Allocate the dictionaries to reduce memory usage
+ 1.6 2 Aug 2024 Remove unneeded dependency on limits.h
+ 1.7 16 May 2025 Remove redundant frees of point list on error
+ Clean out point list structure when freed
*/
-/* Illustrate the use of Z_BLOCK, inflatePrime(), and inflateSetDictionary()
- for random access of a compressed file. A file containing a zlib or gzip
- stream is provided on the command line. The compressed stream is decoded in
- its entirety, and an index built with access points about every SPAN bytes
- in the uncompressed output. The compressed file is left open, and can then
- be read randomly, having to decompress on the average SPAN/2 uncompressed
- bytes before getting to the desired block of data.
-
- An access point can be created at the start of any deflate block, by saving
- the starting file offset and bit of that block, and the 32K bytes of
- uncompressed data that precede that block. Also the uncompressed offset of
- that block is saved to provide a referece for locating a desired starting
- point in the uncompressed stream. build_index() works by decompressing the
- input zlib or gzip stream a block at a time, and at the end of each block
- deciding if enough uncompressed data has gone by to justify the creation of
- a new access point. If so, that point is saved in a data structure that
- grows as needed to accommodate the points.
-
- To use the index, an offset in the uncompressed data is provided, for which
- the latest accees point at or preceding that offset is located in the index.
- The input file is positioned to the specified location in the index, and if
- necessary the first few bits of the compressed data is read from the file.
- inflate is initialized with those bits and the 32K of uncompressed data, and
- the decompression then proceeds until the desired offset in the file is
- reached. Then the decompression continues to read the desired uncompressed
- data from the file.
-
- Another approach would be to generate the index on demand. In that case,
- requests for random access reads from the compressed data would try to use
- the index, but if a read far enough past the end of the index is required,
- then further index entries would be generated and added.
-
- There is some fair bit of overhead to starting inflation for the random
- access, mainly copying the 32K byte dictionary. So if small pieces of the
- file are being accessed, it would make sense to implement a cache to hold
- some lookahead and avoid many calls to extract() for small lengths.
-
- Another way to build an index would be to use inflateCopy(). That would
- not be constrained to have access points at block boundaries, but requires
- more memory per access point, and also cannot be saved to file due to the
- use of pointers in the state. The approach here allows for storage of the
- index in a file.
- */
+// Illustrate the use of Z_BLOCK, inflatePrime(), and inflateSetDictionary()
+// for random access of a compressed file. A file containing a raw deflate
+// stream is provided on the command line. The compressed stream is decoded in
+// its entirety, and an index built with access points about every SPAN bytes
+// in the uncompressed output. The compressed file is left open, and can then
+// be read randomly, having to decompress on the average SPAN/2 uncompressed
+// bytes before getting to the desired block of data.
+//
+// An access point can be created at the start of any deflate block, by saving
+// the starting file offset and bit of that block, and the 32K bytes of
+// uncompressed data that precede that block. Also the uncompressed offset of
+// that block is saved to provide a reference for locating a desired starting
+// point in the uncompressed stream. deflate_index_build() decompresses the
+// input raw deflate stream a block at a time, and at the end of each block
+// decides if enough uncompressed data has gone by to justify the creation of a
+// new access point. If so, that point is saved in a data structure that grows
+// as needed to accommodate the points.
+//
+// To use the index, an offset in the uncompressed data is provided, for which
+// the latest access point at or preceding that offset is located in the index.
+// The input file is positioned to the specified location in the index, and if
+// necessary the first few bits of the compressed data is read from the file.
+// inflate is initialized with those bits and the 32K of uncompressed data, and
+// decompression then proceeds until the desired offset in the file is reached.
+// Then decompression continues to read the requested uncompressed data from
+// the file.
+//
+// There is some fair bit of overhead to starting inflation for the random
+// access, mainly copying the 32K byte dictionary. If small pieces of the file
+// are being accessed, it would make sense to implement a cache to hold some
+// lookahead to avoid many calls to deflate_index_extract() for small lengths.
+//
+// Another way to build an index would be to use inflateCopy(). That would not
+// be constrained to have access points at block boundaries, but would require
+// more memory per access point, and could not be saved to a file due to the
+// use of pointers in the state. The approach here allows for storage of the
+// index in a file.
#include
#include
#include
#include "zlib.h"
+#include "zran.h"
+
+#define WINSIZE 32768U // sliding window size
+#define CHUNK 16384 // file input buffer size
-#define local static
-
-#define SPAN 1048576L /* desired distance between access points */
-#define WINSIZE 32768U /* sliding window size */
-#define CHUNK 16384 /* file input buffer size */
-
-/* access point entry */
-struct point {
- off_t out; /* corresponding offset in uncompressed data */
- off_t in; /* offset in input file of first full byte */
- int bits; /* number of bits (1-7) from byte at in - 1, or 0 */
- unsigned char window[WINSIZE]; /* preceding 32K of uncompressed data */
-};
-
-/* access point list */
-struct access {
- int have; /* number of list entries filled in */
- int size; /* number of list entries allocated */
- struct point *list; /* allocated list */
-};
-
-/* Deallocate an index built by build_index() */
-local void free_index(struct access *index)
-{
+// See comments in zran.h.
+void deflate_index_free(struct deflate_index *index) {
if (index != NULL) {
+ while (index->have)
+ free(index->list[--index->have].window);
free(index->list);
+ index->list = NULL;
+ inflateEnd(&index->strm);
free(index);
}
}
-/* Add an entry to the access point list. If out of memory, deallocate the
- existing list and return NULL. */
-local struct access *addpoint(struct access *index, int bits,
- off_t in, off_t out, unsigned left, unsigned char *window)
-{
- struct point *next;
-
- /* if list is empty, create it (start with eight points) */
- if (index == NULL) {
- index = malloc(sizeof(struct access));
- if (index == NULL) return NULL;
- index->list = malloc(sizeof(struct point) << 3);
- if (index->list == NULL) {
- free(index);
- return NULL;
- }
- index->size = 8;
- index->have = 0;
- }
-
- /* if list is full, make it bigger */
- else if (index->have == index->size) {
- index->size <<= 1;
- next = realloc(index->list, sizeof(struct point) * index->size);
- if (next == NULL) {
- free_index(index);
+// Add an access point to the list. If out of memory, return NULL. index->mode
+// is temporarily the allocated number of access points, until it is time for
+// deflate_index_build() to return. Then index->mode is set to the mode of
+// inflation.
+static struct deflate_index *add_point(struct deflate_index *index, off_t in,
+ off_t out, off_t beg,
+ unsigned char *window) {
+ if (index->have == index->mode) {
+ // The list is full. Make it bigger.
+ index->mode = index->mode ? index->mode << 1 : 8;
+ point_t *next = realloc(index->list, sizeof(point_t) * index->mode);
+ if (next == NULL)
return NULL;
- }
index->list = next;
}
- /* fill in entry and increment how many we have */
- next = index->list + index->have;
- next->bits = bits;
- next->in = in;
+ // Fill in the access point and increment how many we have.
+ point_t *next = (point_t *)(index->list) + index->have++;
+ if (index->have < 0)
+ // Overflowed the int!
+ return NULL;
next->out = out;
- if (left)
- memcpy(next->window, window + WINSIZE - left, left);
- if (left < WINSIZE)
- memcpy(next->window + left, window, WINSIZE - left);
- index->have++;
-
- /* return list, possibly reallocated */
+ next->in = in;
+ next->bits = index->strm.data_type & 7;
+ next->dict = out - beg > WINSIZE ? WINSIZE : (unsigned)(out - beg);
+ next->window = malloc(next->dict);
+ if (next->window == NULL)
+ return NULL;
+ unsigned recent = WINSIZE - index->strm.avail_out;
+ unsigned copy = recent > next->dict ? next->dict : recent;
+ memcpy(next->window + next->dict - copy, window + recent - copy, copy);
+ copy = next->dict - copy;
+ memcpy(next->window, window + WINSIZE - copy, copy);
+
+ // Return the index, which may have been newly allocated or destroyed.
return index;
}
-/* Make one entire pass through the compressed stream and build an index, with
- access points about every span bytes of uncompressed output -- span is
- chosen to balance the speed of random access against the memory requirements
- of the list, about 32K bytes per access point. Note that data after the end
- of the first zlib or gzip stream in the file is ignored. build_index()
- returns the number of access points on success (>= 1), Z_MEM_ERROR for out
- of memory, Z_DATA_ERROR for an error in the input file, or Z_ERRNO for a
- file read error. On success, *built points to the resulting index. */
-local int build_index(FILE *in, off_t span, struct access **built)
-{
- int ret;
- off_t totin, totout; /* our own total counters to avoid 4GB limit */
- off_t last; /* totout value of last access point */
- struct access *index; /* access points being generated */
- z_stream strm;
- unsigned char input[CHUNK];
- unsigned char window[WINSIZE];
-
- /* initialize inflate */
- strm.zalloc = Z_NULL;
- strm.zfree = Z_NULL;
- strm.opaque = Z_NULL;
- strm.avail_in = 0;
- strm.next_in = Z_NULL;
- ret = inflateInit2(&strm, 47); /* automatic zlib or gzip decoding */
- if (ret != Z_OK)
- return ret;
-
- /* inflate the input, maintain a sliding window, and build an index -- this
- also validates the integrity of the compressed data using the check
- information at the end of the gzip or zlib stream */
- totin = totout = last = 0;
- index = NULL; /* will be allocated by first addpoint() */
- strm.avail_out = 0;
+// Decompression modes. These are the inflateInit2() windowBits parameter.
+#define RAW -15
+#define ZLIB 15
+#define GZIP 31
+
+// See comments in zran.h.
+int deflate_index_build(FILE *in, off_t span, struct deflate_index **built) {
+ // If this returns with an error, any attempt to use the index will cleanly
+ // return an error.
+ *built = NULL;
+
+ // Create and initialize the index list.
+ struct deflate_index *index = malloc(sizeof(struct deflate_index));
+ if (index == NULL)
+ return Z_MEM_ERROR;
+ index->have = 0;
+ index->mode = 0; // entries in index->list allocation
+ index->list = NULL;
+ index->strm.state = Z_NULL; // so inflateEnd() can work
+
+ // Set up the inflation state.
+ index->strm.avail_in = 0;
+ index->strm.avail_out = 0;
+ unsigned char buf[CHUNK]; // input buffer
+ unsigned char win[WINSIZE] = {0}; // output sliding window
+ off_t totin = 0; // total bytes read from input
+ off_t totout = 0; // total bytes uncompressed
+ off_t beg = 0; // starting offset of last history reset
+ int mode = 0; // mode: RAW, ZLIB, or GZIP (0 => not set yet)
+
+ // Decompress from in, generating access points along the way.
+ int ret; // the return value from zlib, or Z_ERRNO
+ off_t last; // last access point uncompressed offset
do {
- /* get some compressed data from input file */
- strm.avail_in = fread(input, 1, CHUNK, in);
- if (ferror(in)) {
- ret = Z_ERRNO;
- goto build_index_error;
+ // Assure available input, at least until reaching EOF.
+ if (index->strm.avail_in == 0) {
+ index->strm.avail_in = fread(buf, 1, sizeof(buf), in);
+ totin += index->strm.avail_in;
+ index->strm.next_in = buf;
+ if (index->strm.avail_in < sizeof(buf) && ferror(in)) {
+ ret = Z_ERRNO;
+ break;
+ }
+
+ if (mode == 0) {
+ // At the start of the input -- determine the type. Assume raw
+ // if it is neither zlib nor gzip. This could in theory result
+ // in a false positive for zlib, but in practice the fill bits
+ // after a stored block are always zeros, so a raw stream won't
+ // start with an 8 in the low nybble.
+ mode = index->strm.avail_in == 0 ? RAW : // will fail
+ (index->strm.next_in[0] & 0xf) == 8 ? ZLIB :
+ index->strm.next_in[0] == 0x1f ? GZIP :
+ /* else */ RAW;
+ index->strm.zalloc = Z_NULL;
+ index->strm.zfree = Z_NULL;
+ index->strm.opaque = Z_NULL;
+ ret = inflateInit2(&index->strm, mode);
+ if (ret != Z_OK)
+ break;
+ }
}
- if (strm.avail_in == 0) {
- ret = Z_DATA_ERROR;
- goto build_index_error;
+
+ // Assure available output. This rotates the output through, for use as
+ // a sliding window on the uncompressed data.
+ if (index->strm.avail_out == 0) {
+ index->strm.avail_out = sizeof(win);
+ index->strm.next_out = win;
}
- strm.next_in = input;
-
- /* process all of that, or until end of stream */
- do {
- /* reset sliding window if necessary */
- if (strm.avail_out == 0) {
- strm.avail_out = WINSIZE;
- strm.next_out = window;
- }
- /* inflate until out of input, output, or at end of block --
- update the total input and output counters */
- totin += strm.avail_in;
- totout += strm.avail_out;
- ret = inflate(&strm, Z_BLOCK); /* return at end of block */
- totin -= strm.avail_in;
- totout -= strm.avail_out;
- if (ret == Z_NEED_DICT)
- ret = Z_DATA_ERROR;
- if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR)
- goto build_index_error;
- if (ret == Z_STREAM_END)
- break;
+ if (mode == RAW && index->have == 0)
+ // We skip the inflate() call at the start of raw deflate data in
+ // order generate an access point there. Set data_type to imitate
+ // the end of a header.
+ index->strm.data_type = 0x80;
+ else {
+ // Inflate and update the number of uncompressed bytes.
+ unsigned before = index->strm.avail_out;
+ ret = inflate(&index->strm, Z_BLOCK);
+ totout += before - index->strm.avail_out;
+ }
- /* if at end of block, consider adding an index entry (note that if
- data_type indicates an end-of-block, then all of the
- uncompressed data from that block has been delivered, and none
- of the compressed data after that block has been consumed,
- except for up to seven bits) -- the totout == 0 provides an
- entry point after the zlib or gzip header, and assures that the
- index always has at least one access point; we avoid creating an
- access point after the last block by checking bit 6 of data_type
- */
- if ((strm.data_type & 128) && !(strm.data_type & 64) &&
- (totout == 0 || totout - last > span)) {
- index = addpoint(index, strm.data_type & 7, totin,
- totout, strm.avail_out, window);
- if (index == NULL) {
- ret = Z_MEM_ERROR;
- goto build_index_error;
- }
- last = totout;
+ if ((index->strm.data_type & 0xc0) == 0x80 &&
+ (index->have == 0 || totout - last >= span)) {
+ // We are at the end of a header or a non-last deflate block, so we
+ // can add an access point here. Furthermore, we are either at the
+ // very start for the first access point, or there has been span or
+ // more uncompressed bytes since the last access point, so we want
+ // to add an access point here.
+ index = add_point(index, totin - index->strm.avail_in, totout, beg,
+ win);
+ if (index == NULL) {
+ ret = Z_MEM_ERROR;
+ break;
}
- } while (strm.avail_in != 0);
- } while (ret != Z_STREAM_END);
+ last = totout;
+ }
- /* clean up and return index (release unused entries in list) */
- (void)inflateEnd(&strm);
- index->list = realloc(index->list, sizeof(struct point) * index->have);
- index->size = index->have;
+ if (ret == Z_STREAM_END && mode == GZIP &&
+ (index->strm.avail_in || ungetc(getc(in), in) != EOF)) {
+ // There is more input after the end of a gzip member. Reset the
+ // inflate state to read another gzip member. On success, this will
+ // set ret to Z_OK to continue decompressing.
+ ret = inflateReset2(&index->strm, GZIP);
+ beg = totout; // reset history
+ }
+
+ // Keep going until Z_STREAM_END or error. If the compressed data ends
+ // prematurely without a file read error, Z_BUF_ERROR is returned.
+ } while (ret == Z_OK);
+
+ if (ret != Z_STREAM_END) {
+ // An error was encountered. Discard the index and return a negative
+ // error code.
+ deflate_index_free(index);
+ return ret == Z_NEED_DICT ? Z_DATA_ERROR : ret;
+ }
+
+ // Return the index.
+ index->mode = mode;
+ index->length = totout;
*built = index;
- return index->size;
-
- /* return error */
- build_index_error:
- (void)inflateEnd(&strm);
- if (index != NULL)
- free_index(index);
- return ret;
+ return index->have;
}
-/* Use the index to read len bytes from offset into buf, return bytes read or
- negative for error (Z_DATA_ERROR or Z_MEM_ERROR). If data is requested past
- the end of the uncompressed data, then extract() will return a value less
- than len, indicating how much as actually read into buf. This function
- should not return a data error unless the file was modified since the index
- was generated. extract() may also return Z_ERRNO if there is an error on
- reading or seeking the input file. */
-local int extract(FILE *in, struct access *index, off_t offset,
- unsigned char *buf, int len)
-{
- int ret, skip;
- z_stream strm;
- struct point *here;
- unsigned char input[CHUNK];
- unsigned char discard[WINSIZE];
+#ifdef NOPRIME
+// Support zlib versions before 1.2.3 (July 2005), or incomplete zlib clones
+// that do not have inflatePrime().
+
+# define INFLATEPRIME inflatePreface
+
+// Append the low bits bits of value to in[] at bit position *have, updating
+// *have. value must be zero above its low bits bits. bits must be positive.
+// This assumes that any bits above the *have bits in the last byte are zeros.
+// That assumption is preserved on return, as any bits above *have + bits in
+// the last byte written will be set to zeros.
+static inline void append_bits(unsigned value, int bits,
+ unsigned char *in, int *have) {
+ in += *have >> 3; // where the first bits from value will go
+ int k = *have & 7; // the number of bits already there
+ *have += bits;
+ if (k)
+ *in |= value << k; // write value above the low k bits
+ else
+ *in = value;
+ k = 8 - k; // the number of bits just appended
+ while (bits > k) {
+ value >>= k; // drop the bits appended
+ bits -= k;
+ k = 8; // now at a byte boundary
+ *++in = value;
+ }
+}
+
+// Insert enough bits in the form of empty deflate blocks in front of the
+// low bits bits of value, in order to bring the sequence to a byte boundary.
+// Then feed that to inflate(). This does what inflatePrime() does, except that
+// a negative value of bits is not supported. bits must be in 0..16. If the
+// arguments are invalid, Z_STREAM_ERROR is returned. Otherwise the return
+// value from inflate() is returned.
+static int inflatePreface(z_stream *strm, int bits, int value) {
+ // Check input.
+ if (strm == Z_NULL || bits < 0 || bits > 16)
+ return Z_STREAM_ERROR;
+ if (bits == 0)
+ return Z_OK;
+ value &= (2 << (bits - 1)) - 1;
+
+ // An empty dynamic block with an odd number of bits (95). The high bit of
+ // the last byte is unused.
+ static const unsigned char dyn[] = {
+ 4, 0xe0, 0x81, 8, 0, 0, 0, 0, 0x20, 0xa8, 0xab, 0x1f
+ };
+ const int dynlen = 95; // number of bits in the block
+
+ // Build an input buffer for inflate that is a multiple of eight bits in
+ // length, and that ends with the low bits bits of value.
+ unsigned char in[(dynlen + 3 * 10 + 16 + 7) / 8];
+ int have = 0;
+ if (bits & 1) {
+ // Insert an empty dynamic block to get to an odd number of bits, so
+ // when bits bits from value are appended, we are at an even number of
+ // bits.
+ memcpy(in, dyn, sizeof(dyn));
+ have = dynlen;
+ }
+ while ((have + bits) & 7)
+ // Insert empty fixed blocks until appending bits bits would put us on
+ // a byte boundary. This will insert at most three fixed blocks.
+ append_bits(2, 10, in, &have);
+
+ // Append the bits bits from value, which takes us to a byte boundary.
+ append_bits(value, bits, in, &have);
+
+ // Deliver the input to inflate(). There is no output space provided, but
+ // inflate() can't get stuck waiting on output not ingesting all of the
+ // provided input. The reason is that there will be at most 16 bits of
+ // input from value after the empty deflate blocks (which themselves
+ // generate no output). At least ten bits are needed to generate the first
+ // output byte from a fixed block. The last two bytes of the buffer have to
+ // be ingested in order to get ten bits, which is the most that value can
+ // occupy.
+ strm->avail_in = have >> 3;
+ strm->next_in = in;
+ strm->avail_out = 0;
+ strm->next_out = in; // not used, but can't be NULL
+ return inflate(strm, Z_NO_FLUSH);
+}
+
+#else
+# define INFLATEPRIME inflatePrime
+#endif
- /* proceed only if something reasonable to do */
- if (len < 0)
+// See comments in zran.h.
+ptrdiff_t deflate_index_extract(FILE *in, struct deflate_index *index,
+ off_t offset, unsigned char *buf, size_t len) {
+ // Do a quick sanity check on the index.
+ if (index == NULL || index->have < 1 || index->list[0].out != 0 ||
+ index->strm.state == Z_NULL)
+ return Z_STREAM_ERROR;
+
+ // If nothing to extract, return zero bytes extracted.
+ if (len == 0 || offset < 0 || offset >= index->length)
return 0;
- /* find where in stream to start */
- here = index->list;
- ret = index->have;
- while (--ret && here[1].out <= offset)
- here++;
-
- /* initialize file and inflate state to start there */
- strm.zalloc = Z_NULL;
- strm.zfree = Z_NULL;
- strm.opaque = Z_NULL;
- strm.avail_in = 0;
- strm.next_in = Z_NULL;
- ret = inflateInit2(&strm, -15); /* raw inflate */
+ // Find the access point closest to but not after offset.
+ int lo = -1, hi = index->have;
+ point_t *point = index->list;
+ while (hi - lo > 1) {
+ int mid = (lo + hi) >> 1;
+ if (offset < point[mid].out)
+ hi = mid;
+ else
+ lo = mid;
+ }
+ point += lo;
+
+ // Initialize the input file and prime the inflate engine to start there.
+ int ret = fseeko(in, point->in - (point->bits ? 1 : 0), SEEK_SET);
+ if (ret == -1)
+ return Z_ERRNO;
+ int ch = 0;
+ if (point->bits && (ch = getc(in)) == EOF)
+ return ferror(in) ? Z_ERRNO : Z_BUF_ERROR;
+ index->strm.avail_in = 0;
+ ret = inflateReset2(&index->strm, RAW);
if (ret != Z_OK)
return ret;
- ret = fseeko(in, here->in - (here->bits ? 1 : 0), SEEK_SET);
- if (ret == -1)
- goto extract_ret;
- if (here->bits) {
- ret = getc(in);
- if (ret == -1) {
- ret = ferror(in) ? Z_ERRNO : Z_DATA_ERROR;
- goto extract_ret;
- }
- (void)inflatePrime(&strm, here->bits, ret >> (8 - here->bits));
- }
- (void)inflateSetDictionary(&strm, here->window, WINSIZE);
+ if (point->bits)
+ INFLATEPRIME(&index->strm, point->bits, ch >> (8 - point->bits));
+ inflateSetDictionary(&index->strm, point->window, point->dict);
- /* skip uncompressed bytes until offset reached, then satisfy request */
- offset -= here->out;
- strm.avail_in = 0;
- skip = 1; /* while skipping to offset */
+ // Skip uncompressed bytes until offset reached, then satisfy request.
+ unsigned char input[CHUNK];
+ unsigned char discard[WINSIZE];
+ offset -= point->out; // number of bytes to skip to get to offset
+ size_t left = len; // number of bytes left to read after offset
do {
- /* define where to put uncompressed data, and how much */
- if (offset == 0 && skip) { /* at offset now */
- strm.avail_out = len;
- strm.next_out = buf;
- skip = 0; /* only do this once */
- }
- if (offset > WINSIZE) { /* skip WINSIZE bytes */
- strm.avail_out = WINSIZE;
- strm.next_out = discard;
- offset -= WINSIZE;
+ if (offset) {
+ // Discard up to offset uncompressed bytes.
+ index->strm.avail_out = offset < WINSIZE ? (unsigned)offset :
+ WINSIZE;
+ index->strm.next_out = discard;
}
- else if (offset != 0) { /* last skip */
- strm.avail_out = (unsigned)offset;
- strm.next_out = discard;
- offset = 0;
+ else {
+ // Uncompress up to left bytes into buf.
+ index->strm.avail_out = left < (unsigned)-1 ? (unsigned)left :
+ (unsigned)-1;
+ index->strm.next_out = buf + len - left;
}
- /* uncompress until avail_out filled, or end of stream */
- do {
- if (strm.avail_in == 0) {
- strm.avail_in = fread(input, 1, CHUNK, in);
- if (ferror(in)) {
- ret = Z_ERRNO;
- goto extract_ret;
- }
- if (strm.avail_in == 0) {
- ret = Z_DATA_ERROR;
- goto extract_ret;
- }
- strm.next_in = input;
+ // Uncompress, setting got to the number of bytes uncompressed.
+ if (index->strm.avail_in == 0) {
+ // Assure available input.
+ index->strm.avail_in = fread(input, 1, CHUNK, in);
+ if (index->strm.avail_in < CHUNK && ferror(in)) {
+ ret = Z_ERRNO;
+ break;
}
- ret = inflate(&strm, Z_NO_FLUSH); /* normal inflate */
- if (ret == Z_NEED_DICT)
- ret = Z_DATA_ERROR;
- if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR)
- goto extract_ret;
- if (ret == Z_STREAM_END)
+ index->strm.next_in = input;
+ }
+ unsigned got = index->strm.avail_out;
+ ret = inflate(&index->strm, Z_NO_FLUSH);
+ got -= index->strm.avail_out;
+
+ // Update the appropriate count.
+ if (offset)
+ offset -= got;
+ else {
+ left -= got;
+ if (left == 0)
+ // Request satisfied.
break;
- } while (strm.avail_out != 0);
+ }
- /* if reach end of stream, then don't keep trying to get more */
- if (ret == Z_STREAM_END)
- break;
+ // If we're at the end of a gzip member and there's more to read,
+ // continue to the next gzip member.
+ if (ret == Z_STREAM_END && index->mode == GZIP) {
+ // Discard the gzip trailer.
+ unsigned drop = 8; // length of gzip trailer
+ if (index->strm.avail_in >= drop) {
+ index->strm.avail_in -= drop;
+ index->strm.next_in += drop;
+ }
+ else {
+ // Read and discard the remainder of the gzip trailer.
+ drop -= index->strm.avail_in;
+ index->strm.avail_in = 0;
+ do {
+ if (getc(in) == EOF)
+ // The input does not have a complete trailer.
+ return ferror(in) ? Z_ERRNO : Z_BUF_ERROR;
+ } while (--drop);
+ }
- /* do until offset reached and requested data read, or stream ends */
- } while (skip);
+ if (index->strm.avail_in || ungetc(getc(in), in) != EOF) {
+ // There's more after the gzip trailer. Use inflate to skip the
+ // gzip header and resume the raw inflate there.
+ inflateReset2(&index->strm, GZIP);
+ do {
+ if (index->strm.avail_in == 0) {
+ index->strm.avail_in = fread(input, 1, CHUNK, in);
+ if (index->strm.avail_in < CHUNK && ferror(in)) {
+ ret = Z_ERRNO;
+ break;
+ }
+ index->strm.next_in = input;
+ }
+ index->strm.avail_out = WINSIZE;
+ index->strm.next_out = discard;
+ ret = inflate(&index->strm, Z_BLOCK); // stop after header
+ } while (ret == Z_OK && (index->strm.data_type & 0x80) == 0);
+ if (ret != Z_OK)
+ break;
+ inflateReset2(&index->strm, RAW);
+ }
+ }
- /* compute number of uncompressed bytes read after offset */
- ret = skip ? 0 : len - strm.avail_out;
+ // Continue until we have the requested data, the deflate data has
+ // ended, or an error is encountered.
+ } while (ret == Z_OK);
- /* clean up and return bytes read or error */
- extract_ret:
- (void)inflateEnd(&strm);
- return ret;
+ // Return the number of uncompressed bytes read into buf, or the error.
+ return ret == Z_OK || ret == Z_STREAM_END ? len - left : ret;
}
-/* Demonstrate the use of build_index() and extract() by processing the file
- provided on the command line, and the extracting 16K from about 2/3rds of
- the way through the uncompressed output, and writing that to stdout. */
-int main(int argc, char **argv)
-{
- int len;
- off_t offset;
- FILE *in;
- struct access *index = NULL;
- unsigned char buf[CHUNK];
-
- /* open input file */
- if (argc != 2) {
- fprintf(stderr, "usage: zran file.gz\n");
+#ifdef TEST
+
+#define SPAN 1048576L // desired distance between access points
+#define LEN 16384 // number of bytes to extract
+
+// Demonstrate the use of deflate_index_build() and deflate_index_extract() by
+// processing the file provided on the command line, and extracting LEN bytes
+// from 2/3rds of the way through the uncompressed output, writing that to
+// stdout. An offset can be provided as the second argument, in which case the
+// data is extracted from there instead.
+int main(int argc, char **argv) {
+ // Open the input file.
+ if (argc < 2 || argc > 3) {
+ fprintf(stderr, "usage: zran file.raw [offset]\n");
return 1;
}
- in = fopen(argv[1], "rb");
+ FILE *in = fopen(argv[1], "rb");
if (in == NULL) {
fprintf(stderr, "zran: could not open %s for reading\n", argv[1]);
return 1;
}
- /* build index */
- len = build_index(in, SPAN, &index);
+ // Get optional offset.
+ off_t offset = -1;
+ if (argc == 3) {
+ char *end;
+ offset = strtoll(argv[2], &end, 10);
+ if (*end || offset < 0) {
+ fprintf(stderr, "zran: %s is not a valid offset\n", argv[2]);
+ return 1;
+ }
+ }
+
+ // Build index.
+ struct deflate_index *index = NULL;
+ int len = deflate_index_build(in, SPAN, &index);
if (len < 0) {
fclose(in);
switch (len) {
case Z_MEM_ERROR:
fprintf(stderr, "zran: out of memory\n");
break;
+ case Z_BUF_ERROR:
+ fprintf(stderr, "zran: %s ended prematurely\n", argv[1]);
+ break;
case Z_DATA_ERROR:
fprintf(stderr, "zran: compressed data error in %s\n", argv[1]);
break;
@@ -391,19 +524,23 @@ int main(int argc, char **argv)
}
fprintf(stderr, "zran: built index with %d access points\n", len);
- /* use index by reading some bytes from an arbitrary offset */
- offset = (index->list[index->have - 1].out << 1) / 3;
- len = extract(in, index, offset, buf, CHUNK);
- if (len < 0)
+ // Use index by reading some bytes from an arbitrary offset.
+ unsigned char buf[LEN];
+ if (offset == -1)
+ offset = ((index->length + 1) << 1) / 3;
+ ptrdiff_t got = deflate_index_extract(in, index, offset, buf, LEN);
+ if (got < 0)
fprintf(stderr, "zran: extraction failed: %s error\n",
- len == Z_MEM_ERROR ? "out of memory" : "input corrupted");
+ got == Z_MEM_ERROR ? "out of memory" : "input corrupted");
else {
- fwrite(buf, 1, len, stdout);
- fprintf(stderr, "zran: extracted %d bytes at %llu\n", len, offset);
+ fwrite(buf, 1, got, stdout);
+ fprintf(stderr, "zran: extracted %ld bytes at %lld\n", got, offset);
}
- /* clean up and exit */
- free_index(index);
+ // Clean up and exit.
+ deflate_index_free(index);
fclose(in);
return 0;
}
+
+#endif
diff --git a/zlib/gzclose.c b/zlib/gzclose.c
index caeb99a31..48d6a86f0 100644
--- a/zlib/gzclose.c
+++ b/zlib/gzclose.c
@@ -8,9 +8,7 @@
/* gzclose() is in a separate file so that it is linked in only if it is used.
That way the other gzclose functions can be used instead to avoid linking in
unneeded compression or decompression routines. */
-int ZEXPORT gzclose(file)
- gzFile file;
-{
+int ZEXPORT gzclose(gzFile file) {
#ifndef NO_GZCOMPRESS
gz_statep state;
diff --git a/zlib/gzguts.h b/zlib/gzguts.h
index 990a4d251..266305deb 100644
--- a/zlib/gzguts.h
+++ b/zlib/gzguts.h
@@ -1,5 +1,5 @@
/* gzguts.h -- zlib internal header definitions for gz* operations
- * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler
+ * Copyright (C) 2004-2026 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -7,9 +7,8 @@
# ifndef _LARGEFILE_SOURCE
# define _LARGEFILE_SOURCE 1
# endif
-# ifdef _FILE_OFFSET_BITS
-# undef _FILE_OFFSET_BITS
-# endif
+# undef _FILE_OFFSET_BITS
+# undef _TIME_BITS
#endif
#ifdef HAVE_HIDDEN
@@ -18,6 +17,18 @@
# define ZLIB_INTERNAL
#endif
+#if defined(_WIN32)
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# ifndef _CRT_SECURE_NO_WARNINGS
+# define _CRT_SECURE_NO_WARNINGS
+# endif
+# ifndef _CRT_NONSTDC_NO_DEPRECATE
+# define _CRT_NONSTDC_NO_DEPRECATE
+# endif
+#endif
+
#include
#include "zlib.h"
#ifdef STDC
@@ -26,8 +37,8 @@
# include
#endif
-#ifndef _POSIX_SOURCE
-# define _POSIX_SOURCE
+#ifndef _POSIX_C_SOURCE
+# define _POSIX_C_SOURCE 200112L
#endif
#include
@@ -37,19 +48,13 @@
#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)
# include
+# include
#endif
-#if defined(_WIN32) || defined(__CYGWIN__)
+#if defined(_WIN32) && !defined(WIDECHAR)
# define WIDECHAR
#endif
-#ifdef WINAPI_FAMILY
-# define open _open
-# define read _read
-# define write _write
-# define close _close
-#endif
-
#ifdef NO_DEFLATE /* for compatibility with old definition */
# define NO_GZCOMPRESS
#endif
@@ -73,33 +78,28 @@
#endif
#ifndef HAVE_VSNPRINTF
-# ifdef MSDOS
+# if !defined(NO_vsnprintf) && \
+ (defined(MSDOS) || defined(__TURBOC__) || defined(__SASC) || \
+ defined(VMS) || defined(__OS400) || defined(__MVS__))
/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
but for now we just assume it doesn't. */
# define NO_vsnprintf
# endif
-# ifdef __TURBOC__
-# define NO_vsnprintf
-# endif
# ifdef WIN32
/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
-# if !defined(vsnprintf) && !defined(NO_vsnprintf)
-# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
-# define vsnprintf _vsnprintf
+# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
+# ifndef vsnprintf
+# define vsnprintf _vsnprintf
# endif
# endif
-# endif
-# ifdef __SASC
-# define NO_vsnprintf
-# endif
-# ifdef VMS
-# define NO_vsnprintf
-# endif
-# ifdef __OS400__
-# define NO_vsnprintf
-# endif
-# ifdef __MVS__
-# define NO_vsnprintf
+# elif !defined(__STDC_VERSION__) || __STDC_VERSION__-0 < 199901L
+/* Otherwise if C89/90, assume no C99 snprintf() or vsnprintf() */
+# ifndef NO_snprintf
+# define NO_snprintf
+# endif
+# ifndef NO_vsnprintf
+# define NO_vsnprintf
+# endif
# endif
#endif
@@ -119,8 +119,8 @@
/* gz* functions always use library allocation functions */
#ifndef STDC
- extern voidp malloc OF((uInt size));
- extern void free OF((voidpf ptr));
+ extern voidp malloc(uInt size);
+ extern void free(voidpf ptr);
#endif
/* get errno and strerror definition */
@@ -138,10 +138,10 @@
/* provide prototypes for these when building zlib without LFS */
#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
- ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
- ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
- ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
- ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
+ ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *);
+ ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int);
+ ZEXTERN z_off64_t ZEXPORT gztell64(gzFile);
+ ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile);
#endif
/* default memLevel */
@@ -183,16 +183,18 @@ typedef struct {
unsigned char *out; /* output buffer (double-sized when reading) */
int direct; /* 0 if processing gzip, 1 if transparent */
/* just for reading */
+ int junk; /* -1 = start, 1 = junk candidate, 0 = in gzip */
int how; /* 0: get header, 1: copy, 2: decompress */
+ int again; /* true if EAGAIN or EWOULDBLOCK on last i/o */
z_off64_t start; /* where the gzip data started, for rewinding */
int eof; /* true if end of input file reached */
int past; /* true if read requested past end */
/* just for writing */
int level; /* compression level */
int strategy; /* compression strategy */
+ int reset; /* true if a reset is pending after a Z_FINISH */
/* seek request */
z_off64_t skip; /* amount to skip (already rewound if backwards) */
- int seek; /* true if seek request pending */
/* error information */
int err; /* error code */
char *msg; /* error message */
@@ -202,17 +204,13 @@ typedef struct {
typedef gz_state FAR *gz_statep;
/* shared functions */
-void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *));
+void ZLIB_INTERNAL gz_error(gz_statep, int, const char *);
#if defined UNDER_CE
-char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error));
+char ZLIB_INTERNAL *gz_strwinerror(DWORD error);
#endif
/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
value -- needed when comparing unsigned to z_off64_t, which is signed
(possible z_off64_t types off_t, off64_t, and long are all signed) */
-#ifdef INT_MAX
-# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
-#else
-unsigned ZLIB_INTERNAL gz_intmax OF((void));
-# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
-#endif
+unsigned ZLIB_INTERNAL gz_intmax(void);
+#define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
diff --git a/zlib/gzlib.c b/zlib/gzlib.c
index 4105e6aff..7a37a96cf 100644
--- a/zlib/gzlib.c
+++ b/zlib/gzlib.c
@@ -1,23 +1,19 @@
/* gzlib.c -- zlib functions common to reading and writing gzip files
- * Copyright (C) 2004-2017 Mark Adler
+ * Copyright (C) 2004-2026 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "gzguts.h"
-#if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__)
+#if defined(__DJGPP__)
+# define LSEEK llseek
+#elif defined(_WIN32) && !defined(__BORLANDC__) && !defined(UNDER_CE)
# define LSEEK _lseeki64
-#else
-#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
+#elif defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
# define LSEEK lseek64
#else
# define LSEEK lseek
#endif
-#endif
-
-/* Local functions */
-local void gz_reset OF((gz_statep));
-local gzFile gz_open OF((const void *, int, const char *));
#if defined UNDER_CE
@@ -30,9 +26,7 @@ local gzFile gz_open OF((const void *, int, const char *));
The gz_strwinerror function does not change the current setting of
GetLastError. */
-char ZLIB_INTERNAL *gz_strwinerror (error)
- DWORD error;
-{
+char ZLIB_INTERNAL *gz_strwinerror(DWORD error) {
static char buf[1024];
wchar_t *msgbuf;
@@ -58,7 +52,7 @@ char ZLIB_INTERNAL *gz_strwinerror (error)
msgbuf[chars] = 0;
}
- wcstombs(buf, msgbuf, chars + 1);
+ wcstombs(buf, msgbuf, chars + 1); /* assumes buf is big enough */
LocalFree(msgbuf);
}
else {
@@ -72,39 +66,34 @@ char ZLIB_INTERNAL *gz_strwinerror (error)
#endif /* UNDER_CE */
/* Reset gzip file state */
-local void gz_reset(state)
- gz_statep state;
-{
+local void gz_reset(gz_statep state) {
state->x.have = 0; /* no output data available */
if (state->mode == GZ_READ) { /* for reading ... */
state->eof = 0; /* not at end of file */
state->past = 0; /* have not read past end yet */
state->how = LOOK; /* look for gzip header */
+ state->junk = -1; /* mark first member */
}
- state->seek = 0; /* no seek request pending */
+ else /* for writing ... */
+ state->reset = 0; /* no deflateReset pending */
+ state->again = 0; /* no stalled i/o yet */
+ state->skip = 0; /* no seek request pending */
gz_error(state, Z_OK, NULL); /* clear error */
state->x.pos = 0; /* no uncompressed data yet */
state->strm.avail_in = 0; /* no input data yet */
}
/* Open a gzip file either by name or file descriptor. */
-local gzFile gz_open(path, fd, mode)
- const void *path;
- int fd;
- const char *mode;
-{
+local gzFile gz_open(const void *path, int fd, const char *mode) {
gz_statep state;
z_size_t len;
- int oflag;
-#ifdef O_CLOEXEC
- int cloexec = 0;
-#endif
+ int oflag = 0;
#ifdef O_EXCL
int exclusive = 0;
#endif
/* check input */
- if (path == NULL)
+ if (path == NULL || mode == NULL)
return NULL;
/* allocate gzFile structure to return */
@@ -113,6 +102,7 @@ local gzFile gz_open(path, fd, mode)
return NULL;
state->size = 0; /* no buffers allocated yet */
state->want = GZBUFSIZE; /* requested buffer size */
+ state->err = Z_OK; /* no error yet */
state->msg = NULL; /* no error message yet */
/* interpret mode */
@@ -143,7 +133,7 @@ local gzFile gz_open(path, fd, mode)
break;
#ifdef O_CLOEXEC
case 'e':
- cloexec = 1;
+ oflag |= O_CLOEXEC;
break;
#endif
#ifdef O_EXCL
@@ -163,6 +153,14 @@ local gzFile gz_open(path, fd, mode)
case 'F':
state->strategy = Z_FIXED;
break;
+ case 'G':
+ state->direct = -1;
+ break;
+#ifdef O_NONBLOCK
+ case 'N':
+ oflag |= O_NONBLOCK;
+ break;
+#endif
case 'T':
state->direct = 1;
break;
@@ -178,22 +176,30 @@ local gzFile gz_open(path, fd, mode)
return NULL;
}
- /* can't force transparent read */
+ /* direct is 0, 1 if "T", or -1 if "G" (last "G" or "T" wins) */
if (state->mode == GZ_READ) {
- if (state->direct) {
+ if (state->direct == 1) {
+ /* can't force a transparent read */
free(state);
return NULL;
}
- state->direct = 1; /* for empty file */
+ if (state->direct == 0)
+ /* default when reading is auto-detect of gzip vs. transparent --
+ start with a transparent assumption in case of an empty file */
+ state->direct = 1;
}
+ else if (state->direct == -1) {
+ /* "G" has no meaning when writing -- disallow it */
+ free(state);
+ return NULL;
+ }
+ /* if reading, direct == 1 for auto-detect, -1 for gzip only; if writing or
+ appending, direct == 0 for gzip, 1 for transparent (copy in to out) */
/* save the path name for error messages */
#ifdef WIDECHAR
- if (fd == -2) {
+ if (fd == -2)
len = wcstombs(NULL, path, 0);
- if (len == (z_size_t)-1)
- len = 0;
- }
else
#endif
len = strlen((const char *)path);
@@ -203,29 +209,29 @@ local gzFile gz_open(path, fd, mode)
return NULL;
}
#ifdef WIDECHAR
- if (fd == -2)
+ if (fd == -2) {
if (len)
wcstombs(state->path, path, len + 1);
else
*(state->path) = 0;
+ }
else
#endif
+ {
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
(void)snprintf(state->path, len + 1, "%s", (const char *)path);
#else
strcpy(state->path, path);
#endif
+ }
/* compute the flags for open() */
- oflag =
+ oflag |=
#ifdef O_LARGEFILE
O_LARGEFILE |
#endif
#ifdef O_BINARY
O_BINARY |
-#endif
-#ifdef O_CLOEXEC
- (cloexec ? O_CLOEXEC : 0) |
#endif
(state->mode == GZ_READ ?
O_RDONLY :
@@ -238,11 +244,23 @@ local gzFile gz_open(path, fd, mode)
O_APPEND)));
/* open the file with the appropriate flags (or just use fd) */
- state->fd = fd > -1 ? fd : (
+ if (fd == -1)
+ state->fd = open((const char *)path, oflag, 0666);
#ifdef WIDECHAR
- fd == -2 ? _wopen(path, oflag, 0666) :
+ else if (fd == -2)
+ state->fd = _wopen(path, oflag, _S_IREAD | _S_IWRITE);
#endif
- open((const char *)path, oflag, 0666));
+ else {
+#ifdef O_NONBLOCK
+ if (oflag & O_NONBLOCK)
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
+#endif
+#ifdef O_CLOEXEC
+ if (oflag & O_CLOEXEC)
+ fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | O_CLOEXEC);
+#endif
+ state->fd = fd;
+ }
if (state->fd == -1) {
free(state->path);
free(state);
@@ -267,26 +285,17 @@ local gzFile gz_open(path, fd, mode)
}
/* -- see zlib.h -- */
-gzFile ZEXPORT gzopen(path, mode)
- const char *path;
- const char *mode;
-{
+gzFile ZEXPORT gzopen(const char *path, const char *mode) {
return gz_open(path, -1, mode);
}
/* -- see zlib.h -- */
-gzFile ZEXPORT gzopen64(path, mode)
- const char *path;
- const char *mode;
-{
+gzFile ZEXPORT gzopen64(const char *path, const char *mode) {
return gz_open(path, -1, mode);
}
/* -- see zlib.h -- */
-gzFile ZEXPORT gzdopen(fd, mode)
- int fd;
- const char *mode;
-{
+gzFile ZEXPORT gzdopen(int fd, const char *mode) {
char *path; /* identifier for error messages */
gzFile gz;
@@ -304,19 +313,13 @@ gzFile ZEXPORT gzdopen(fd, mode)
/* -- see zlib.h -- */
#ifdef WIDECHAR
-gzFile ZEXPORT gzopen_w(path, mode)
- const wchar_t *path;
- const char *mode;
-{
+gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode) {
return gz_open(path, -2, mode);
}
#endif
/* -- see zlib.h -- */
-int ZEXPORT gzbuffer(file, size)
- gzFile file;
- unsigned size;
-{
+int ZEXPORT gzbuffer(gzFile file, unsigned size) {
gz_statep state;
/* get internal structure and check integrity */
@@ -333,16 +336,14 @@ int ZEXPORT gzbuffer(file, size)
/* check and set requested size */
if ((size << 1) < size)
return -1; /* need to be able to double it */
- if (size < 2)
- size = 2; /* need two bytes to check magic header */
+ if (size < 8)
+ size = 8; /* needed to behave well with flushing */
state->want = size;
return 0;
}
/* -- see zlib.h -- */
-int ZEXPORT gzrewind(file)
- gzFile file;
-{
+int ZEXPORT gzrewind(gzFile file) {
gz_statep state;
/* get internal structure */
@@ -363,11 +364,7 @@ int ZEXPORT gzrewind(file)
}
/* -- see zlib.h -- */
-z_off64_t ZEXPORT gzseek64(file, offset, whence)
- gzFile file;
- z_off64_t offset;
- int whence;
-{
+z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) {
unsigned n;
z_off64_t ret;
gz_statep state;
@@ -390,20 +387,21 @@ z_off64_t ZEXPORT gzseek64(file, offset, whence)
/* normalize offset to a SEEK_CUR specification */
if (whence == SEEK_SET)
offset -= state->x.pos;
- else if (state->seek)
- offset += state->skip;
- state->seek = 0;
+ else {
+ offset += state->past ? 0 : state->skip;
+ state->skip = 0;
+ }
/* if within raw area while reading, just go there */
if (state->mode == GZ_READ && state->how == COPY &&
state->x.pos + offset >= 0) {
- ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
+ ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR);
if (ret == -1)
return -1;
state->x.have = 0;
state->eof = 0;
state->past = 0;
- state->seek = 0;
+ state->skip = 0;
gz_error(state, Z_OK, NULL);
state->strm.avail_in = 0;
state->x.pos += offset;
@@ -432,19 +430,12 @@ z_off64_t ZEXPORT gzseek64(file, offset, whence)
}
/* request skip (if not zero) */
- if (offset) {
- state->seek = 1;
- state->skip = offset;
- }
+ state->skip = offset;
return state->x.pos + offset;
}
/* -- see zlib.h -- */
-z_off_t ZEXPORT gzseek(file, offset, whence)
- gzFile file;
- z_off_t offset;
- int whence;
-{
+z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) {
z_off64_t ret;
ret = gzseek64(file, (z_off64_t)offset, whence);
@@ -452,9 +443,7 @@ z_off_t ZEXPORT gzseek(file, offset, whence)
}
/* -- see zlib.h -- */
-z_off64_t ZEXPORT gztell64(file)
- gzFile file;
-{
+z_off64_t ZEXPORT gztell64(gzFile file) {
gz_statep state;
/* get internal structure and check integrity */
@@ -465,13 +454,11 @@ z_off64_t ZEXPORT gztell64(file)
return -1;
/* return position */
- return state->x.pos + (state->seek ? state->skip : 0);
+ return state->x.pos + (state->past ? 0 : state->skip);
}
/* -- see zlib.h -- */
-z_off_t ZEXPORT gztell(file)
- gzFile file;
-{
+z_off_t ZEXPORT gztell(gzFile file) {
z_off64_t ret;
ret = gztell64(file);
@@ -479,9 +466,7 @@ z_off_t ZEXPORT gztell(file)
}
/* -- see zlib.h -- */
-z_off64_t ZEXPORT gzoffset64(file)
- gzFile file;
-{
+z_off64_t ZEXPORT gzoffset64(gzFile file) {
z_off64_t offset;
gz_statep state;
@@ -502,9 +487,7 @@ z_off64_t ZEXPORT gzoffset64(file)
}
/* -- see zlib.h -- */
-z_off_t ZEXPORT gzoffset(file)
- gzFile file;
-{
+z_off_t ZEXPORT gzoffset(gzFile file) {
z_off64_t ret;
ret = gzoffset64(file);
@@ -512,9 +495,7 @@ z_off_t ZEXPORT gzoffset(file)
}
/* -- see zlib.h -- */
-int ZEXPORT gzeof(file)
- gzFile file;
-{
+int ZEXPORT gzeof(gzFile file) {
gz_statep state;
/* get internal structure and check integrity */
@@ -529,10 +510,7 @@ int ZEXPORT gzeof(file)
}
/* -- see zlib.h -- */
-const char * ZEXPORT gzerror(file, errnum)
- gzFile file;
- int *errnum;
-{
+const char * ZEXPORT gzerror(gzFile file, int *errnum) {
gz_statep state;
/* get internal structure and check integrity */
@@ -550,9 +528,7 @@ const char * ZEXPORT gzerror(file, errnum)
}
/* -- see zlib.h -- */
-void ZEXPORT gzclearerr(file)
- gzFile file;
-{
+void ZEXPORT gzclearerr(gzFile file) {
gz_statep state;
/* get internal structure and check integrity */
@@ -576,11 +552,7 @@ void ZEXPORT gzclearerr(file)
memory). Simply save the error message as a static string. If there is an
allocation failure constructing the error message, then convert the error to
out of memory. */
-void ZLIB_INTERNAL gz_error(state, err, msg)
- gz_statep state;
- int err;
- const char *msg;
-{
+void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) {
/* free previously allocated message and clear */
if (state->msg != NULL) {
if (state->err != Z_MEM_ERROR)
@@ -589,7 +561,7 @@ void ZLIB_INTERNAL gz_error(state, err, msg)
}
/* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
- if (err != Z_OK && err != Z_BUF_ERROR)
+ if (err != Z_OK && err != Z_BUF_ERROR && !state->again)
state->x.have = 0;
/* set error code, and if no message, then done */
@@ -617,21 +589,21 @@ void ZLIB_INTERNAL gz_error(state, err, msg)
#endif
}
-#ifndef INT_MAX
/* portably return maximum value for an int (when limits.h presumed not
available) -- we need to do this to cover cases where 2's complement not
used, since C standard permits 1's complement and sign-bit representations,
otherwise we could just use ((unsigned)-1) >> 1 */
-unsigned ZLIB_INTERNAL gz_intmax()
-{
- unsigned p, q;
+unsigned ZLIB_INTERNAL gz_intmax(void) {
+#ifdef INT_MAX
+ return INT_MAX;
+#else
+ unsigned p = 1, q;
- p = 1;
do {
q = p;
p <<= 1;
p++;
} while (p > q);
return q >> 1;
-}
#endif
+}
diff --git a/zlib/gzread.c b/zlib/gzread.c
index 08881ee09..45dd4dbfa 100644
--- a/zlib/gzread.c
+++ b/zlib/gzread.c
@@ -1,43 +1,43 @@
/* gzread.c -- zlib functions for reading gzip files
- * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler
+ * Copyright (C) 2004-2026 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "gzguts.h"
-/* Local functions */
-local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
-local int gz_avail OF((gz_statep));
-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.
This function needs to loop on read(), since read() is not guaranteed to
- read the number of bytes requested, depending on the type of descriptor. */
-local int gz_load(state, buf, len, have)
- gz_statep state;
- unsigned char *buf;
- unsigned len;
- unsigned *have;
-{
+ read the number of bytes requested, depending on the type of descriptor. It
+ also needs to loop to manage the fact that read() returns an int. If the
+ descriptor is non-blocking and read() returns with no data in order to avoid
+ blocking, then gz_load() will return 0 if some data has been read, or -1 if
+ no data has been read. Either way, state->again is set true to indicate a
+ non-blocking event. If errno is non-zero on return, then there was an error
+ signaled from read(). *have is set to the number of bytes read. */
+local int gz_load(gz_statep state, unsigned char *buf, unsigned len,
+ unsigned *have) {
int ret;
unsigned get, max = ((unsigned)-1 >> 2) + 1;
+ state->again = 0;
+ errno = 0;
*have = 0;
do {
get = len - *have;
if (get > max)
get = max;
- ret = read(state->fd, buf + *have, get);
+ ret = (int)read(state->fd, buf + *have, get);
if (ret <= 0)
break;
*have += (unsigned)ret;
} while (*have < len);
if (ret < 0) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ state->again = 1;
+ if (*have != 0)
+ return 0;
+ }
gz_error(state, Z_ERRNO, zstrerror());
return -1;
}
@@ -53,9 +53,7 @@ local int gz_load(state, buf, len, have)
If strm->avail_in != 0, then the current data is moved to the beginning of
the input buffer, and then the remainder of the buffer is loaded with the
available data from the input file. */
-local int gz_avail(state)
- gz_statep state;
-{
+local int gz_avail(gz_statep state) {
unsigned got;
z_streamp strm = &(state->strm);
@@ -65,10 +63,14 @@ local int gz_avail(state)
if (strm->avail_in) { /* copy what's there to the start */
unsigned char *p = state->in;
unsigned const char *q = strm->next_in;
- unsigned n = strm->avail_in;
- do {
- *p++ = *q++;
- } while (--n);
+
+ if (q != p) {
+ unsigned n = strm->avail_in;
+
+ do {
+ *p++ = *q++;
+ } while (--n);
+ }
}
if (gz_load(state, state->in + strm->avail_in,
state->size - strm->avail_in, &got) == -1)
@@ -88,9 +90,7 @@ local int gz_avail(state)
case, all further file reads will be directly to either the output buffer or
a user buffer. If decompressing, the inflate state will be initialized.
gz_look() will return 0 on success or -1 on failure. */
-local int gz_look(state)
- gz_statep state;
-{
+local int gz_look(gz_statep state) {
z_streamp strm = &(state->strm);
/* allocate read buffers and inflate memory */
@@ -121,60 +121,63 @@ local int gz_look(state)
}
}
- /* get at least the magic bytes in the input buffer */
- if (strm->avail_in < 2) {
- if (gz_avail(state) == -1)
- return -1;
- if (strm->avail_in == 0)
- return 0;
- }
-
- /* look for gzip magic bytes -- if there, do gzip decoding (note: there is
- a logical dilemma here when considering the case of a partially written
- gzip file, to wit, if a single 31 byte is written, then we cannot tell
- whether this is a single-byte file, or just a partially written gzip
- file -- for here we assume that if a gzip file is being written, then
- the header will be written in a single operation, so that reading a
- single byte is sufficient indication that it is not a gzip file) */
- if (strm->avail_in > 1 &&
- strm->next_in[0] == 31 && strm->next_in[1] == 139) {
+ /* if transparent reading is disabled, which would only be at the start, or
+ if we're looking for a gzip member after the first one, which is not at
+ the start, then proceed directly to look for a gzip member next */
+ if (state->direct == -1 || state->junk == 0) {
inflateReset(strm);
state->how = GZIP;
+ state->junk = state->junk != -1;
state->direct = 0;
return 0;
}
- /* no gzip header -- if we were decoding gzip before, then this is trailing
- garbage. Ignore the trailing garbage and finish. */
- if (state->direct == 0) {
- strm->avail_in = 0;
- state->eof = 1;
- state->x.have = 0;
+ /* otherwise we're at the start with auto-detect -- we check to see if the
+ first four bytes could be gzip header in order to decide whether or not
+ this will be a transparent read */
+
+ /* load any header bytes into the input buffer -- if the input is empty,
+ then it's not an error as this is a transparent read of zero bytes */
+ if (gz_avail(state) == -1)
+ return -1;
+ if (strm->avail_in == 0 || (state->again && strm->avail_in < 4))
+ /* if non-blocking input stalled before getting four bytes, then
+ return and wait until a later call has accumulated enough */
+ return 0;
+
+ /* see if this is (likely) gzip input -- if the first four bytes are
+ consistent with a gzip header, then go look for the first gzip member,
+ otherwise proceed to copy the input transparently */
+ if (strm->avail_in > 3 &&
+ strm->next_in[0] == 31 && strm->next_in[1] == 139 &&
+ strm->next_in[2] == 8 && strm->next_in[3] < 32) {
+ inflateReset(strm);
+ state->how = GZIP;
+ state->junk = 1;
+ state->direct = 0;
return 0;
}
- /* doing raw i/o, copy any leftover input to output -- this assumes that
+ /* doing raw i/o: copy any leftover input to output -- this assumes that
the output buffer is larger than the input buffer, which also assures
space for gzungetc() */
state->x.next = state->out;
- if (strm->avail_in) {
- memcpy(state->x.next, strm->next_in, strm->avail_in);
- state->x.have = strm->avail_in;
- strm->avail_in = 0;
- }
+ memcpy(state->x.next, strm->next_in, strm->avail_in);
+ state->x.have = strm->avail_in;
+ strm->avail_in = 0;
state->how = COPY;
- state->direct = 1;
return 0;
}
/* Decompress from input to the provided next_out and avail_out in the state.
On return, state->x.have and state->x.next point to the just decompressed
- data. If the gzip stream completes, state->how is reset to LOOK to look for
- the next gzip stream or raw data, once state->x.have is depleted. Returns 0
- on success, -1 on failure. */
-local int gz_decomp(state)
- gz_statep state;
-{
+ data. If the gzip stream completes, state->how is reset to LOOK to look for
+ the next gzip stream or raw data, once state->x.have is depleted. Returns 0
+ on success, -1 on failure. If EOF is reached when looking for more input to
+ complete the gzip member, then an unexpected end of file error is raised.
+ If there is no more input, but state->again is true, then EOF has not been
+ reached, and no error is raised. */
+local int gz_decomp(gz_statep state) {
int ret = Z_OK;
unsigned had;
z_streamp strm = &(state->strm);
@@ -183,28 +186,41 @@ local int gz_decomp(state)
had = strm->avail_out;
do {
/* get more input for inflate() */
- if (strm->avail_in == 0 && gz_avail(state) == -1)
- return -1;
+ if (strm->avail_in == 0 && gz_avail(state) == -1) {
+ ret = state->err;
+ break;
+ }
if (strm->avail_in == 0) {
- gz_error(state, Z_BUF_ERROR, "unexpected end of file");
+ if (!state->again)
+ gz_error(state, Z_BUF_ERROR, "unexpected end of file");
break;
}
/* decompress and handle errors */
ret = inflate(strm, Z_NO_FLUSH);
+ if (strm->avail_out < had)
+ /* any decompressed data marks this as a real gzip stream */
+ state->junk = 0;
if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
gz_error(state, Z_STREAM_ERROR,
"internal error: inflate stream corrupt");
- return -1;
+ break;
}
if (ret == Z_MEM_ERROR) {
gz_error(state, Z_MEM_ERROR, "out of memory");
- return -1;
+ break;
}
if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
+ if (state->junk == 1) { /* trailing garbage is ok */
+ strm->avail_in = 0;
+ state->eof = 1;
+ state->how = LOOK;
+ ret = Z_OK;
+ break;
+ }
gz_error(state, Z_DATA_ERROR,
strm->msg == NULL ? "compressed data error" : strm->msg);
- return -1;
+ break;
}
} while (strm->avail_out && ret != Z_STREAM_END);
@@ -213,11 +229,14 @@ local int gz_decomp(state)
state->x.next = strm->next_out - state->x.have;
/* if the gzip stream completed successfully, look for another */
- if (ret == Z_STREAM_END)
+ if (ret == Z_STREAM_END) {
+ state->junk = 0;
state->how = LOOK;
+ return 0;
+ }
- /* good decompression */
- return 0;
+ /* return decompression status */
+ return ret != Z_OK ? -1 : 0;
}
/* Fetch data and put it in the output buffer. Assumes state->x.have is 0.
@@ -226,9 +245,7 @@ local int gz_decomp(state)
looked for to determine whether to copy or decompress. Returns -1 on error,
otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the
end of the input file has been reached and all data has been processed. */
-local int gz_fetch(state)
- gz_statep state;
-{
+local int gz_fetch(gz_statep state) {
z_streamp strm = &(state->strm);
do {
@@ -250,28 +267,31 @@ local int gz_fetch(state)
strm->next_out = state->out;
if (gz_decomp(state) == -1)
return -1;
+ break;
+ default:
+ gz_error(state, Z_STREAM_ERROR, "state corrupt");
+ return -1;
}
} while (state->x.have == 0 && (!state->eof || strm->avail_in));
return 0;
}
-/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */
-local int gz_skip(state, len)
- gz_statep state;
- z_off64_t len;
-{
+/* Skip state->skip (> 0) uncompressed bytes of output. Return -1 on error, 0
+ on success. */
+local int gz_skip(gz_statep state) {
unsigned n;
/* skip over len bytes or reach end-of-file, whichever comes first */
- while (len)
+ do {
/* skip over whatever is in output buffer */
if (state->x.have) {
- n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?
- (unsigned)len : state->x.have;
+ n = GT_OFF(state->x.have) ||
+ (z_off64_t)state->x.have > state->skip ?
+ (unsigned)state->skip : state->x.have;
state->x.have -= n;
state->x.next += n;
state->x.pos += n;
- len -= n;
+ state->skip -= n;
}
/* output buffer empty -- return if we're at the end of the input */
@@ -284,39 +304,37 @@ local int gz_skip(state, len)
if (gz_fetch(state) == -1)
return -1;
}
+ } while (state->skip);
return 0;
}
/* 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;
- z_size_t len;
-{
+ 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. If there was an error, but some uncompressed
+ bytes were read before the error, then that count is returned. The error is
+ still recorded, and so is deferred until the next call. */
+local z_size_t gz_read(gz_statep state, voidp buf, z_size_t len) {
z_size_t got;
unsigned n;
+ int err;
/* if len is zero, avoid unnecessary operations */
if (len == 0)
return 0;
/* process a skip request */
- if (state->seek) {
- state->seek = 0;
- if (gz_skip(state, state->skip) == -1)
- return 0;
- }
+ if (state->skip && gz_skip(state) == -1)
+ return 0;
/* get len bytes to buf, or less than len if at the end */
got = 0;
+ err = 0;
do {
/* set n to the maximum amount of len that fits in an unsigned int */
- n = -1;
+ n = (unsigned)-1;
if (n > len)
- n = len;
+ n = (unsigned)len;
/* first just try copying data from the output buffer */
if (state->x.have) {
@@ -325,37 +343,36 @@ local z_size_t gz_read(state, buf, len)
memcpy(buf, state->x.next, n);
state->x.next += n;
state->x.have -= n;
+ if (state->err != Z_OK)
+ /* caught deferred error from gz_fetch() */
+ err = -1;
}
/* output buffer empty -- return if we're at the end of the input */
- else if (state->eof && state->strm.avail_in == 0) {
- state->past = 1; /* tried to read past end */
+ else if (state->eof && state->strm.avail_in == 0)
break;
- }
/* need output data -- for small len or new stream load up our output
- buffer */
+ buffer, so that gzgetc() can be fast */
else if (state->how == LOOK || n < (state->size << 1)) {
/* get more output, looking for header if required */
- if (gz_fetch(state) == -1)
- return 0;
+ if (gz_fetch(state) == -1 && state->x.have == 0)
+ /* if state->x.have != 0, error will be caught after copy */
+ err = -1;
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 */
}
/* large len -- read directly into user buffer */
- else if (state->how == COPY) { /* read directly */
- if (gz_load(state, (unsigned char *)buf, n, &n) == -1)
- return 0;
- }
+ else if (state->how == COPY) /* read directly */
+ err = gz_load(state, (unsigned char *)buf, n, &n);
/* large len -- decompress directly into user buffer */
else { /* state->how == GZIP */
state->strm.avail_out = n;
state->strm.next_out = (unsigned char *)buf;
- if (gz_decomp(state) == -1)
- return 0;
+ err = gz_decomp(state);
n = state->x.have;
state->x.have = 0;
}
@@ -365,29 +382,31 @@ local z_size_t gz_read(state, buf, len)
buf = (char *)buf + n;
got += n;
state->x.pos += n;
- } while (len);
+ } while (len && !err);
+
+ /* note read past eof */
+ if (len && state->eof)
+ state->past = 1;
/* 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;
-{
+int ZEXPORT gzread(gzFile file, voidp buf, unsigned len) {
gz_statep state;
- /* get internal structure */
+ /* get internal structure and check that it's for reading */
if (file == NULL)
return -1;
state = (gz_statep)file;
+ if (state->mode != GZ_READ)
+ return -1;
- /* 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))
+ /* check that there was no (serious) error */
+ if (state->err != Z_OK && state->err != Z_BUF_ERROR && !state->again)
return -1;
+ gz_error(state, Z_OK, NULL);
/* since an int is returned, make sure len fits in one, otherwise return
with an error (this avoids a flaw in the interface) */
@@ -397,35 +416,42 @@ int ZEXPORT gzread(file, buf, len)
}
/* read len or fewer bytes to buf */
- len = gz_read(state, buf, len);
+ len = (unsigned)gz_read(state, buf, len);
/* check for an error */
- if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR)
- return -1;
+ if (len == 0) {
+ if (state->err != Z_OK && state->err != Z_BUF_ERROR)
+ return -1;
+ if (state->again) {
+ /* non-blocking input stalled after some input was read, but no
+ uncompressed bytes were produced -- let the application know
+ this isn't EOF */
+ gz_error(state, Z_ERRNO, zstrerror());
+ return -1;
+ }
+ }
- /* return the number of bytes read (this is assured to fit in an int) */
+ /* return the number of bytes read */
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 ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems,
+ gzFile file) {
z_size_t len;
gz_statep state;
- /* get internal structure */
+ /* get internal structure and check that it's for reading */
if (file == NULL)
return 0;
state = (gz_statep)file;
+ if (state->mode != GZ_READ)
+ return 0;
- /* 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))
+ /* check that there was no (serious) error */
+ if (state->err != Z_OK && state->err != Z_BUF_ERROR && !state->again)
return 0;
+ gz_error(state, Z_OK, NULL);
/* compute bytes to read -- error on overflow */
len = nitems * size;
@@ -447,23 +473,21 @@ z_size_t ZEXPORT gzfread(buf, size, nitems, file)
# define gzgetc act_z_gzgetc
# endif
#endif
-
-int ZEXPORT gzgetc(file)
- gzFile file;
-{
- int ret;
+int ZEXPORT gzgetc(gzFile file) {
unsigned char buf[1];
gz_statep state;
- /* get internal structure */
+ /* get internal structure and check that it's for reading */
if (file == NULL)
return -1;
state = (gz_statep)file;
+ if (state->mode != GZ_READ)
+ return -1;
- /* 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))
+ /* check that there was no (serious) error */
+ if (state->err != Z_OK && state->err != Z_BUF_ERROR && !state->again)
return -1;
+ gz_error(state, Z_OK, NULL);
/* try output buffer (no need to check for skip request) */
if (state->x.have) {
@@ -473,39 +497,36 @@ int ZEXPORT gzgetc(file)
}
/* nothing there -- try gz_read() */
- ret = gz_read(state, buf, 1);
- return ret < 1 ? -1 : buf[0];
+ return gz_read(state, buf, 1) < 1 ? -1 : buf[0];
}
-int ZEXPORT gzgetc_(file)
-gzFile file;
-{
+int ZEXPORT gzgetc_(gzFile file) {
return gzgetc(file);
}
/* -- see zlib.h -- */
-int ZEXPORT gzungetc(c, file)
- int c;
- gzFile file;
-{
+int ZEXPORT gzungetc(int c, gzFile file) {
gz_statep state;
- /* get internal structure */
+ /* get internal structure and check that it's for reading */
if (file == NULL)
return -1;
state = (gz_statep)file;
+ if (state->mode != GZ_READ)
+ return -1;
- /* 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))
+ /* in case this was just opened, set up the input buffer */
+ if (state->how == LOOK && state->x.have == 0)
+ (void)gz_look(state);
+
+ /* check that there was no (serious) error */
+ if (state->err != Z_OK && state->err != Z_BUF_ERROR && !state->again)
return -1;
+ gz_error(state, Z_OK, NULL);
/* process a skip request */
- if (state->seek) {
- state->seek = 0;
- if (gz_skip(state, state->skip) == -1)
- return -1;
- }
+ if (state->skip && gz_skip(state) == -1)
+ return -1;
/* can't push EOF */
if (c < 0)
@@ -531,6 +552,7 @@ int ZEXPORT gzungetc(c, file)
if (state->x.next == state->out) {
unsigned char *src = state->out + state->x.have;
unsigned char *dest = state->out + (state->size << 1);
+
while (src > state->out)
*--dest = *--src;
state->x.next = dest;
@@ -544,42 +566,37 @@ int ZEXPORT gzungetc(c, file)
}
/* -- see zlib.h -- */
-char * ZEXPORT gzgets(file, buf, len)
- gzFile file;
- char *buf;
- int len;
-{
+char * ZEXPORT gzgets(gzFile file, char *buf, int len) {
unsigned left, n;
char *str;
unsigned char *eol;
gz_statep state;
- /* check parameters and get internal structure */
+ /* check parameters, get internal structure, and check that it's for
+ reading */
if (file == NULL || buf == NULL || len < 1)
return NULL;
state = (gz_statep)file;
+ if (state->mode != GZ_READ)
+ return NULL;
- /* 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))
+ /* check that there was no (serious) error */
+ if (state->err != Z_OK && state->err != Z_BUF_ERROR && !state->again)
return NULL;
+ gz_error(state, Z_OK, NULL);
/* process a skip request */
- if (state->seek) {
- state->seek = 0;
- if (gz_skip(state, state->skip) == -1)
- return NULL;
- }
+ if (state->skip && gz_skip(state) == -1)
+ return NULL;
- /* copy output bytes up to new line or len - 1, whichever comes first --
- append a terminating zero to the string (we don't check for a zero in
- the contents, let the user worry about that) */
+ /* copy output up to a new line, len-1 bytes, or there is no more output,
+ whichever comes first */
str = buf;
left = (unsigned)len - 1;
if (left) do {
/* assure that something is in the output buffer */
if (state->x.have == 0 && gz_fetch(state) == -1)
- return NULL; /* error */
+ break; /* error */
if (state->x.have == 0) { /* end of file */
state->past = 1; /* read past end */
break; /* return what we have */
@@ -600,7 +617,9 @@ char * ZEXPORT gzgets(file, buf, len)
buf += n;
} while (left && eol == NULL);
- /* return terminated string, or if nothing, end of file */
+ /* append a terminating zero to the string (we don't check for a zero in
+ the contents, let the user worry about that) -- return the terminated
+ string, or if nothing was read, NULL */
if (buf == str)
return NULL;
buf[0] = 0;
@@ -608,9 +627,7 @@ char * ZEXPORT gzgets(file, buf, len)
}
/* -- see zlib.h -- */
-int ZEXPORT gzdirect(file)
- gzFile file;
-{
+int ZEXPORT gzdirect(gzFile file) {
gz_statep state;
/* get internal structure */
@@ -624,22 +641,18 @@ int ZEXPORT gzdirect(file)
(void)gz_look(state);
/* return 1 if transparent, 0 if processing a gzip stream */
- return state->direct;
+ return state->direct == 1;
}
/* -- see zlib.h -- */
-int ZEXPORT gzclose_r(file)
- gzFile file;
-{
+int ZEXPORT gzclose_r(gzFile file) {
int ret, err;
gz_statep state;
- /* get internal structure */
+ /* get internal structure and check that it's for reading */
if (file == NULL)
return Z_STREAM_ERROR;
state = (gz_statep)file;
-
- /* check that we're reading */
if (state->mode != GZ_READ)
return Z_STREAM_ERROR;
diff --git a/zlib/gzwrite.c b/zlib/gzwrite.c
index c7b5651d7..13a3700a8 100644
--- a/zlib/gzwrite.c
+++ b/zlib/gzwrite.c
@@ -1,22 +1,14 @@
/* gzwrite.c -- zlib functions for writing gzip files
- * Copyright (C) 2004-2017 Mark Adler
+ * Copyright (C) 2004-2026 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "gzguts.h"
-/* Local functions */
-local int gz_init OF((gz_statep));
-local int gz_comp OF((gz_statep, int));
-local int gz_zero OF((gz_statep, z_off64_t));
-local z_size_t gz_write OF((gz_statep, voidpc, z_size_t));
-
/* Initialize state for writing a gzip file. Mark initialization by setting
state->size to non-zero. Return -1 on a memory allocation failure, or 0 on
success. */
-local int gz_init(state)
- gz_statep state;
-{
+local int gz_init(gz_statep state) {
int ret;
z_streamp strm = &(state->strm);
@@ -70,10 +62,7 @@ local int gz_init(state)
deflate() flush value. If flush is Z_FINISH, then the deflate() state is
reset to start a new gzip stream. If gz->direct is true, then simply write
to the output file without compressing, and ignore flush. */
-local int gz_comp(state, flush)
- gz_statep state;
- int flush;
-{
+local int gz_comp(gz_statep state, int flush) {
int ret, writ;
unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
z_streamp strm = &(state->strm);
@@ -85,9 +74,13 @@ local int gz_comp(state, flush)
/* write directly if requested */
if (state->direct) {
while (strm->avail_in) {
+ errno = 0;
+ state->again = 0;
put = strm->avail_in > max ? max : strm->avail_in;
- writ = write(state->fd, strm->next_in, put);
+ writ = (int)write(state->fd, strm->next_in, put);
if (writ < 0) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ state->again = 1;
gz_error(state, Z_ERRNO, zstrerror());
return -1;
}
@@ -97,6 +90,16 @@ local int gz_comp(state, flush)
return 0;
}
+ /* check for a pending reset */
+ if (state->reset) {
+ /* don't start a new gzip member unless there is data to write and
+ we're not flushing */
+ if (strm->avail_in == 0 && flush == Z_NO_FLUSH)
+ return 0;
+ deflateReset(strm);
+ state->reset = 0;
+ }
+
/* run deflate() on provided input until it produces no more output */
ret = Z_OK;
do {
@@ -105,10 +108,14 @@ local int gz_comp(state, flush)
if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
(flush != Z_FINISH || ret == Z_STREAM_END))) {
while (strm->next_out > state->x.next) {
+ errno = 0;
+ state->again = 0;
put = strm->next_out - state->x.next > (int)max ? max :
(unsigned)(strm->next_out - state->x.next);
- writ = write(state->fd, state->x.next, put);
+ writ = (int)write(state->fd, state->x.next, put);
if (writ < 0) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ state->again = 1;
gz_error(state, Z_ERRNO, zstrerror());
return -1;
}
@@ -134,19 +141,18 @@ local int gz_comp(state, flush)
/* if that completed a deflate stream, allow another to start */
if (flush == Z_FINISH)
- deflateReset(strm);
+ state->reset = 1;
/* all done, no errors */
return 0;
}
-/* Compress len zeros to output. Return -1 on a write error or memory
- allocation failure by gz_comp(), or 0 on success. */
-local int gz_zero(state, len)
- gz_statep state;
- z_off64_t len;
-{
- int first;
+/* Compress state->skip (> 0) zeros to output. Return -1 on a write error or
+ memory allocation failure by gz_comp(), or 0 on success. state->skip is
+ updated with the number of successfully written zeros, in case there is a
+ stall on a non-blocking write destination. */
+local int gz_zero(gz_statep state) {
+ int first, ret;
unsigned n;
z_streamp strm = &(state->strm);
@@ -154,33 +160,34 @@ local int gz_zero(state, len)
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
return -1;
- /* compress len zeros (len guaranteed > 0) */
+ /* compress state->skip zeros */
first = 1;
- while (len) {
- n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
- (unsigned)len : state->size;
+ do {
+ n = GT_OFF(state->size) || (z_off64_t)state->size > state->skip ?
+ (unsigned)state->skip : state->size;
if (first) {
memset(state->in, 0, n);
first = 0;
}
strm->avail_in = n;
strm->next_in = state->in;
+ ret = gz_comp(state, Z_NO_FLUSH);
+ n -= strm->avail_in;
state->x.pos += n;
- if (gz_comp(state, Z_NO_FLUSH) == -1)
+ state->skip -= n;
+ if (ret == -1)
return -1;
- len -= n;
- }
+ } while (state->skip);
return 0;
}
/* Write len bytes from buf to file. Return the number of bytes written. If
- the returned value is less than len, then there was an error. */
-local z_size_t gz_write(state, buf, len)
- gz_statep state;
- voidpc buf;
- z_size_t len;
-{
+ the returned value is less than len, then there was an error. If the error
+ was a non-blocking stall, then the number of bytes consumed is returned.
+ For any other error, 0 is returned. */
+local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) {
z_size_t put = len;
+ int ret;
/* if len is zero, avoid unnecessary operations */
if (len == 0)
@@ -191,16 +198,13 @@ local z_size_t gz_write(state, buf, len)
return 0;
/* check for seek request */
- if (state->seek) {
- state->seek = 0;
- if (gz_zero(state, state->skip) == -1)
- return 0;
- }
+ if (state->skip && gz_zero(state) == -1)
+ return 0;
/* for small len, copy to input buffer, otherwise compress directly */
if (len < state->size) {
/* copy to input buffer, compress when full */
- do {
+ for (;;) {
unsigned have, copy;
if (state->strm.avail_in == 0)
@@ -209,15 +213,17 @@ local z_size_t gz_write(state, buf, len)
state->in);
copy = state->size - have;
if (copy > len)
- copy = len;
+ copy = (unsigned)len;
memcpy(state->in + have, buf, copy);
state->strm.avail_in += copy;
state->x.pos += copy;
buf = (const char *)buf + copy;
len -= copy;
- if (len && gz_comp(state, Z_NO_FLUSH) == -1)
- return 0;
- } while (len);
+ if (len == 0)
+ break;
+ if (gz_comp(state, Z_NO_FLUSH) == -1)
+ return state->again ? put - len : 0;
+ }
}
else {
/* consume whatever's left in the input buffer */
@@ -228,13 +234,16 @@ local z_size_t gz_write(state, buf, len)
state->strm.next_in = (z_const Bytef *)buf;
do {
unsigned n = (unsigned)-1;
+
if (n > len)
- n = len;
+ n = (unsigned)len;
state->strm.avail_in = n;
+ ret = gz_comp(state, Z_NO_FLUSH);
+ n -= state->strm.avail_in;
state->x.pos += n;
- if (gz_comp(state, Z_NO_FLUSH) == -1)
- return 0;
len -= n;
+ if (ret == -1)
+ return state->again ? put - len : 0;
} while (len);
}
@@ -243,11 +252,7 @@ local z_size_t gz_write(state, buf, len)
}
/* -- see zlib.h -- */
-int ZEXPORT gzwrite(file, buf, len)
- gzFile file;
- voidpc buf;
- unsigned len;
-{
+int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) {
gz_statep state;
/* get internal structure */
@@ -255,9 +260,10 @@ int ZEXPORT gzwrite(file, buf, len)
return 0;
state = (gz_statep)file;
- /* check that we're writing and that there's no error */
- if (state->mode != GZ_WRITE || state->err != Z_OK)
+ /* check that we're writing and that there's no (serious) error */
+ if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again))
return 0;
+ gz_error(state, Z_OK, NULL);
/* since an int is returned, make sure len fits in one, otherwise return
with an error (this avoids a flaw in the interface) */
@@ -271,12 +277,8 @@ int ZEXPORT gzwrite(file, buf, len)
}
/* -- see zlib.h -- */
-z_size_t ZEXPORT gzfwrite(buf, size, nitems, file)
- voidpc buf;
- z_size_t size;
- z_size_t nitems;
- gzFile file;
-{
+z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems,
+ gzFile file) {
z_size_t len;
gz_statep state;
@@ -285,9 +287,10 @@ z_size_t ZEXPORT gzfwrite(buf, size, nitems, file)
return 0;
state = (gz_statep)file;
- /* check that we're writing and that there's no error */
- if (state->mode != GZ_WRITE || state->err != Z_OK)
+ /* check that we're writing and that there's no (serious) error */
+ if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again))
return 0;
+ gz_error(state, Z_OK, NULL);
/* compute bytes to read -- error on overflow */
len = nitems * size;
@@ -301,10 +304,7 @@ z_size_t ZEXPORT gzfwrite(buf, size, nitems, file)
}
/* -- see zlib.h -- */
-int ZEXPORT gzputc(file, c)
- gzFile file;
- int c;
-{
+int ZEXPORT gzputc(gzFile file, int c) {
unsigned have;
unsigned char buf[1];
gz_statep state;
@@ -316,16 +316,14 @@ int ZEXPORT gzputc(file, c)
state = (gz_statep)file;
strm = &(state->strm);
- /* check that we're writing and that there's no error */
- if (state->mode != GZ_WRITE || state->err != Z_OK)
+ /* check that we're writing and that there's no (serious) error */
+ if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again))
return -1;
+ gz_error(state, Z_OK, NULL);
/* check for seek request */
- if (state->seek) {
- state->seek = 0;
- if (gz_zero(state, state->skip) == -1)
- return -1;
- }
+ if (state->skip && gz_zero(state) == -1)
+ return -1;
/* try writing to input buffer for speed (state->size == 0 if buffer not
initialized) */
@@ -349,12 +347,8 @@ int ZEXPORT gzputc(file, c)
}
/* -- see zlib.h -- */
-int ZEXPORT gzputs(file, str)
- gzFile file;
- const char *str;
-{
- int ret;
- z_size_t len;
+int ZEXPORT gzputs(gzFile file, const char *s) {
+ z_size_t len, put;
gz_statep state;
/* get internal structure */
@@ -362,24 +356,59 @@ int ZEXPORT gzputs(file, str)
return -1;
state = (gz_statep)file;
- /* check that we're writing and that there's no error */
- if (state->mode != GZ_WRITE || state->err != Z_OK)
+ /* check that we're writing and that there's no (serious) error */
+ if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again))
return -1;
+ gz_error(state, Z_OK, NULL);
/* write string */
- len = strlen(str);
- ret = gz_write(state, str, len);
- return ret == 0 && len != 0 ? -1 : ret;
+ len = strlen(s);
+ if ((int)len < 0 || (unsigned)len != len) {
+ gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
+ return -1;
+ }
+ put = gz_write(state, s, len);
+ return len && put == 0 ? -1 : (int)put;
+}
+
+#if (((!defined(STDC) && !defined(Z_HAVE_STDARG_H)) || !defined(NO_vsnprintf)) && \
+ (defined(STDC) || defined(Z_HAVE_STDARG_H) || !defined(NO_snprintf))) || \
+ defined(ZLIB_INSECURE)
+/* If the second half of the input buffer is occupied, write out the contents.
+ If there is any input remaining due to a non-blocking stall on write, move
+ it to the start of the buffer. Return true if this did not open up the
+ second half of the buffer. state->err should be checked after this to
+ handle a gz_comp() error. */
+local int gz_vacate(gz_statep state) {
+ z_streamp strm;
+
+ strm = &(state->strm);
+ if (strm->next_in + strm->avail_in <= state->in + state->size)
+ return 0;
+ (void)gz_comp(state, Z_NO_FLUSH);
+ if (strm->avail_in == 0) {
+ strm->next_in = state->in;
+ return 0;
+ }
+ memmove(state->in, strm->next_in, strm->avail_in);
+ strm->next_in = state->in;
+ return strm->avail_in > state->size;
}
+#endif
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
#include
/* -- see zlib.h -- */
-int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
-{
- int len;
- unsigned left;
+int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) {
+#if defined(NO_vsnprintf) && !defined(ZLIB_INSECURE)
+#warning "vsnprintf() not available -- gzprintf() stub returns Z_STREAM_ERROR"
+#warning "you can recompile with ZLIB_INSECURE defined to use vsprintf()"
+ /* prevent use of insecure vsprintf(), unless purposefully requested */
+ (void)file, (void)format, (void)va;
+ return Z_STREAM_ERROR;
+#else
+ int len, ret;
char *next;
gz_statep state;
z_streamp strm;
@@ -390,24 +419,34 @@ int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
state = (gz_statep)file;
strm = &(state->strm);
- /* check that we're writing and that there's no error */
- if (state->mode != GZ_WRITE || state->err != Z_OK)
+ /* check that we're writing and that there's no (serious) error */
+ if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again))
return Z_STREAM_ERROR;
+ gz_error(state, Z_OK, NULL);
/* make sure we have some buffer space */
if (state->size == 0 && gz_init(state) == -1)
return state->err;
/* check for seek request */
- if (state->seek) {
- state->seek = 0;
- if (gz_zero(state, state->skip) == -1)
- return state->err;
- }
+ if (state->skip && gz_zero(state) == -1)
+ return state->err;
/* do the printf() into the input buffer, put length in len -- the input
- buffer is double-sized just for this function, so there is guaranteed to
- be state->size bytes available after the current contents */
+ buffer is double-sized just for this function, so there should be
+ state->size bytes available after the current contents */
+ ret = gz_vacate(state);
+ if (state->err) {
+ if (ret && state->again) {
+ /* There was a non-blocking stall on write, resulting in the part
+ of the second half of the output buffer being occupied. Return
+ a Z_BUF_ERROR to let the application know that this gzprintf()
+ needs to be retried. */
+ gz_error(state, Z_BUF_ERROR, "stalled write on gzprintf");
+ }
+ if (!state->again)
+ return state->err;
+ }
if (strm->avail_in == 0)
strm->next_in = state->in;
next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
@@ -433,23 +472,19 @@ int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
return 0;
- /* update buffer and position, compress first half if past that */
+ /* update buffer and position */
strm->avail_in += (unsigned)len;
state->x.pos += len;
- if (strm->avail_in >= state->size) {
- left = strm->avail_in - state->size;
- strm->avail_in = state->size;
- if (gz_comp(state, Z_NO_FLUSH) == -1)
- return state->err;
- memcpy(state->in, state->in + state->size, left);
- strm->next_in = state->in;
- strm->avail_in = left;
- }
+
+ /* write out buffer if more than half is occupied */
+ ret = gz_vacate(state);
+ if (state->err && !state->again)
+ return state->err;
return len;
+#endif
}
-int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
-{
+int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) {
va_list va;
int ret;
@@ -462,13 +497,21 @@ int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
#else /* !STDC && !Z_HAVE_STDARG_H */
/* -- see zlib.h -- */
-int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
- a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
- gzFile file;
- const char *format;
- int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
- a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
-{
+int ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3,
+ int a4, int a5, int a6, int a7, int a8, int a9, int a10,
+ int a11, int a12, int a13, int a14, int a15, int a16,
+ int a17, int a18, int a19, int a20) {
+#if defined(NO_snprintf) && !defined(ZLIB_INSECURE)
+#warning "snprintf() not available -- gzprintf() stub returns Z_STREAM_ERROR"
+#warning "you can recompile with ZLIB_INSECURE defined to use sprintf()"
+ /* prevent use of insecure sprintf(), unless purposefully requested */
+ (void)file, (void)format, (void)a1, (void)a2, (void)a3, (void)a4, (void)a5,
+ (void)a6, (void)a7, (void)a8, (void)a9, (void)a10, (void)a11, (void)a12,
+ (void)a13, (void)a14, (void)a15, (void)a16, (void)a17, (void)a18,
+ (void)a19, (void)a20;
+ return Z_STREAM_ERROR;
+#else
+ int ret;
unsigned len, left;
char *next;
gz_statep state;
@@ -484,24 +527,34 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
if (sizeof(int) != sizeof(void *))
return Z_STREAM_ERROR;
- /* check that we're writing and that there's no error */
- if (state->mode != GZ_WRITE || state->err != Z_OK)
+ /* check that we're writing and that there's no (serious) error */
+ if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again))
return Z_STREAM_ERROR;
+ gz_error(state, Z_OK, NULL);
/* make sure we have some buffer space */
if (state->size == 0 && gz_init(state) == -1)
- return state->error;
+ return state->err;
/* check for seek request */
- if (state->seek) {
- state->seek = 0;
- if (gz_zero(state, state->skip) == -1)
- return state->error;
- }
+ if (state->skip && gz_zero(state) == -1)
+ return state->err;
/* do the printf() into the input buffer, put length in len -- the input
buffer is double-sized just for this function, so there is guaranteed to
be state->size bytes available after the current contents */
+ ret = gz_vacate(state);
+ if (state->err) {
+ if (ret && state->again) {
+ /* There was a non-blocking stall on write, resulting in the part
+ of the second half of the output buffer being occupied. Return
+ a Z_BUF_ERROR to let the application know that this gzprintf()
+ needs to be retried. */
+ gz_error(state, Z_BUF_ERROR, "stalled write on gzprintf");
+ }
+ if (!state->again)
+ return state->err;
+ }
if (strm->avail_in == 0)
strm->next_in = state->in;
next = (char *)(strm->next_in + strm->avail_in);
@@ -535,25 +588,19 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
/* update buffer and position, compress first half if past that */
strm->avail_in += len;
state->x.pos += len;
- if (strm->avail_in >= state->size) {
- left = strm->avail_in - state->size;
- strm->avail_in = state->size;
- if (gz_comp(state, Z_NO_FLUSH) == -1)
- return state->err;
- memcpy(state->in, state->in + state->size, left);
- strm->next_in = state->in;
- strm->avail_in = left;
- }
+
+ /* write out buffer if more than half is occupied */
+ ret = gz_vacate(state);
+ if (state->err && !state->again)
+ return state->err;
return (int)len;
+#endif
}
#endif
/* -- see zlib.h -- */
-int ZEXPORT gzflush(file, flush)
- gzFile file;
- int flush;
-{
+int ZEXPORT gzflush(gzFile file, int flush) {
gz_statep state;
/* get internal structure */
@@ -561,20 +608,18 @@ int ZEXPORT gzflush(file, flush)
return Z_STREAM_ERROR;
state = (gz_statep)file;
- /* check that we're writing and that there's no error */
- if (state->mode != GZ_WRITE || state->err != Z_OK)
+ /* check that we're writing and that there's no (serious) error */
+ if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again))
return Z_STREAM_ERROR;
+ gz_error(state, Z_OK, NULL);
/* check flush parameter */
if (flush < 0 || flush > Z_FINISH)
return Z_STREAM_ERROR;
/* check for seek request */
- if (state->seek) {
- state->seek = 0;
- if (gz_zero(state, state->skip) == -1)
- return state->err;
- }
+ if (state->skip && gz_zero(state) == -1)
+ return state->err;
/* compress remaining data with requested flush */
(void)gz_comp(state, flush);
@@ -582,11 +627,7 @@ int ZEXPORT gzflush(file, flush)
}
/* -- see zlib.h -- */
-int ZEXPORT gzsetparams(file, level, strategy)
- gzFile file;
- int level;
- int strategy;
-{
+int ZEXPORT gzsetparams(gzFile file, int level, int strategy) {
gz_statep state;
z_streamp strm;
@@ -596,20 +637,19 @@ int ZEXPORT gzsetparams(file, level, strategy)
state = (gz_statep)file;
strm = &(state->strm);
- /* check that we're writing and that there's no error */
- if (state->mode != GZ_WRITE || state->err != Z_OK)
+ /* check that we're compressing and that there's no (serious) error */
+ if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again) ||
+ state->direct)
return Z_STREAM_ERROR;
+ gz_error(state, Z_OK, NULL);
/* if no change is requested, then do nothing */
if (level == state->level && strategy == state->strategy)
return Z_OK;
/* check for seek request */
- if (state->seek) {
- state->seek = 0;
- if (gz_zero(state, state->skip) == -1)
- return state->err;
- }
+ if (state->skip && gz_zero(state) == -1)
+ return state->err;
/* change compression parameters for subsequent input */
if (state->size) {
@@ -624,9 +664,7 @@ int ZEXPORT gzsetparams(file, level, strategy)
}
/* -- see zlib.h -- */
-int ZEXPORT gzclose_w(file)
- gzFile file;
-{
+int ZEXPORT gzclose_w(gzFile file) {
int ret = Z_OK;
gz_statep state;
@@ -640,11 +678,8 @@ int ZEXPORT gzclose_w(file)
return Z_STREAM_ERROR;
/* check for seek request */
- if (state->seek) {
- state->seek = 0;
- if (gz_zero(state, state->skip) == -1)
- ret = state->err;
- }
+ if (state->skip && gz_zero(state) == -1)
+ ret = state->err;
/* flush, free memory, and close file */
if (gz_comp(state, Z_FINISH) == -1)
diff --git a/zlib/infback.c b/zlib/infback.c
index 59679ecbf..e6443feb4 100644
--- a/zlib/infback.c
+++ b/zlib/infback.c
@@ -1,5 +1,5 @@
/* infback.c -- inflate using a call-back interface
- * Copyright (C) 1995-2016 Mark Adler
+ * Copyright (C) 1995-2026 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -15,9 +15,6 @@
#include "inflate.h"
#include "inffast.h"
-/* function prototypes */
-local void fixedtables OF((struct inflate_state FAR *state));
-
/*
strm provides memory allocation functions in zalloc and zfree, or
Z_NULL to use the library memory allocation functions.
@@ -25,13 +22,9 @@ local void fixedtables OF((struct inflate_state FAR *state));
windowBits is in the range 8..15, and window is a user-supplied
window and output buffer that is 2**windowBits bytes.
*/
-int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
-z_streamp strm;
-int windowBits;
-unsigned char FAR *window;
-const char *version;
-int stream_size;
-{
+int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits,
+ unsigned char FAR *window, const char *version,
+ int stream_size) {
struct inflate_state FAR *state;
if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
@@ -53,7 +46,7 @@ int stream_size;
#ifdef Z_SOLO
return Z_STREAM_ERROR;
#else
- strm->zfree = zcfree;
+ strm->zfree = zcfree;
#endif
state = (struct inflate_state FAR *)ZALLOC(strm, 1,
sizeof(struct inflate_state));
@@ -66,62 +59,10 @@ int stream_size;
state->window = window;
state->wnext = 0;
state->whave = 0;
+ state->sane = 1;
return Z_OK;
}
-/*
- Return state with length and distance decoding tables and index sizes set to
- fixed code decoding. Normally this returns fixed tables from inffixed.h.
- If BUILDFIXED is defined, then instead this routine builds the tables the
- first time it's called, and returns those tables the first time and
- thereafter. This reduces the size of the code by about 2K bytes, in
- exchange for a little execution time. However, BUILDFIXED should not be
- used for threaded applications, since the rewriting of the tables and virgin
- may not be thread-safe.
- */
-local void fixedtables(state)
-struct inflate_state FAR *state;
-{
-#ifdef BUILDFIXED
- static int virgin = 1;
- static code *lenfix, *distfix;
- static code fixed[544];
-
- /* build fixed huffman tables if first call (may not be thread safe) */
- if (virgin) {
- unsigned sym, bits;
- static code *next;
-
- /* literal/length table */
- sym = 0;
- while (sym < 144) state->lens[sym++] = 8;
- while (sym < 256) state->lens[sym++] = 9;
- while (sym < 280) state->lens[sym++] = 7;
- while (sym < 288) state->lens[sym++] = 8;
- next = fixed;
- lenfix = next;
- bits = 9;
- inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
-
- /* distance table */
- sym = 0;
- while (sym < 32) state->lens[sym++] = 5;
- distfix = next;
- bits = 5;
- inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
-
- /* do this just once */
- virgin = 0;
- }
-#else /* !BUILDFIXED */
-# include "inffixed.h"
-#endif /* BUILDFIXED */
- state->lencode = lenfix;
- state->lenbits = 9;
- state->distcode = distfix;
- state->distbits = 5;
-}
-
/* Macros for inflateBack(): */
/* Load returned state from inflate_fast() */
@@ -247,13 +188,8 @@ struct inflate_state FAR *state;
inflateBack() can also return Z_STREAM_ERROR if the input parameters
are not correct, i.e. strm is Z_NULL or the state was not initialized.
*/
-int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
-z_streamp strm;
-in_func in;
-void FAR *in_desc;
-out_func out;
-void FAR *out_desc;
-{
+int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc,
+ out_func out, void FAR *out_desc) {
struct inflate_state FAR *state;
z_const unsigned char FAR *next; /* next input */
unsigned char FAR *put; /* next output */
@@ -306,7 +242,7 @@ void FAR *out_desc;
state->mode = STORED;
break;
case 1: /* fixed block */
- fixedtables(state);
+ inflate_fixed(state);
Tracev((stderr, "inflate: fixed codes block%s\n",
state->last ? " (last)" : ""));
state->mode = LEN; /* decode codes */
@@ -316,8 +252,8 @@ void FAR *out_desc;
state->last ? " (last)" : ""));
state->mode = TABLE;
break;
- case 3:
- strm->msg = (char *)"invalid block type";
+ default:
+ strm->msg = (z_const char *)"invalid block type";
state->mode = BAD;
}
DROPBITS(2);
@@ -328,7 +264,7 @@ void FAR *out_desc;
BYTEBITS(); /* go to byte boundary */
NEEDBITS(32);
if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
- strm->msg = (char *)"invalid stored block lengths";
+ strm->msg = (z_const char *)"invalid stored block lengths";
state->mode = BAD;
break;
}
@@ -366,7 +302,8 @@ void FAR *out_desc;
DROPBITS(4);
#ifndef PKZIP_BUG_WORKAROUND
if (state->nlen > 286 || state->ndist > 30) {
- strm->msg = (char *)"too many length or distance symbols";
+ strm->msg = (z_const char *)
+ "too many length or distance symbols";
state->mode = BAD;
break;
}
@@ -388,7 +325,7 @@ void FAR *out_desc;
ret = inflate_table(CODES, state->lens, 19, &(state->next),
&(state->lenbits), state->work);
if (ret) {
- strm->msg = (char *)"invalid code lengths set";
+ strm->msg = (z_const char *)"invalid code lengths set";
state->mode = BAD;
break;
}
@@ -411,7 +348,8 @@ void FAR *out_desc;
NEEDBITS(here.bits + 2);
DROPBITS(here.bits);
if (state->have == 0) {
- strm->msg = (char *)"invalid bit length repeat";
+ strm->msg = (z_const char *)
+ "invalid bit length repeat";
state->mode = BAD;
break;
}
@@ -434,7 +372,8 @@ void FAR *out_desc;
DROPBITS(7);
}
if (state->have + copy > state->nlen + state->ndist) {
- strm->msg = (char *)"invalid bit length repeat";
+ strm->msg = (z_const char *)
+ "invalid bit length repeat";
state->mode = BAD;
break;
}
@@ -448,7 +387,8 @@ void FAR *out_desc;
/* check for end-of-block code (better have one) */
if (state->lens[256] == 0) {
- strm->msg = (char *)"invalid code -- missing end-of-block";
+ strm->msg = (z_const char *)
+ "invalid code -- missing end-of-block";
state->mode = BAD;
break;
}
@@ -462,7 +402,7 @@ void FAR *out_desc;
ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
&(state->lenbits), state->work);
if (ret) {
- strm->msg = (char *)"invalid literal/lengths set";
+ strm->msg = (z_const char *)"invalid literal/lengths set";
state->mode = BAD;
break;
}
@@ -471,12 +411,13 @@ void FAR *out_desc;
ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
&(state->next), &(state->distbits), state->work);
if (ret) {
- strm->msg = (char *)"invalid distances set";
+ strm->msg = (z_const char *)"invalid distances set";
state->mode = BAD;
break;
}
Tracev((stderr, "inflate: codes ok\n"));
state->mode = LEN;
+ /* fallthrough */
case LEN:
/* use inflate_fast() if we have enough input and output */
@@ -529,7 +470,7 @@ void FAR *out_desc;
/* invalid code */
if (here.op & 64) {
- strm->msg = (char *)"invalid literal/length code";
+ strm->msg = (z_const char *)"invalid literal/length code";
state->mode = BAD;
break;
}
@@ -561,7 +502,7 @@ void FAR *out_desc;
}
DROPBITS(here.bits);
if (here.op & 64) {
- strm->msg = (char *)"invalid distance code";
+ strm->msg = (z_const char *)"invalid distance code";
state->mode = BAD;
break;
}
@@ -576,7 +517,7 @@ void FAR *out_desc;
}
if (state->offset > state->wsize - (state->whave < state->wsize ?
left : 0)) {
- strm->msg = (char *)"invalid distance too far back";
+ strm->msg = (z_const char *)"invalid distance too far back";
state->mode = BAD;
break;
}
@@ -604,33 +545,33 @@ void FAR *out_desc;
break;
case DONE:
- /* inflate stream terminated properly -- write leftover output */
+ /* inflate stream terminated properly */
ret = Z_STREAM_END;
- if (left < state->wsize) {
- if (out(out_desc, state->window, state->wsize - left))
- ret = Z_BUF_ERROR;
- }
goto inf_leave;
case BAD:
ret = Z_DATA_ERROR;
goto inf_leave;
- default: /* can't happen, but makes compilers happy */
+ default:
+ /* can't happen, but makes compilers happy */
ret = Z_STREAM_ERROR;
goto inf_leave;
}
- /* Return unused input */
+ /* Write leftover output and return unused input */
inf_leave:
+ if (left < state->wsize) {
+ if (out(out_desc, state->window, state->wsize - left) &&
+ ret == Z_STREAM_END)
+ ret = Z_BUF_ERROR;
+ }
strm->next_in = next;
strm->avail_in = have;
return ret;
}
-int ZEXPORT inflateBackEnd(strm)
-z_streamp strm;
-{
+int ZEXPORT inflateBackEnd(z_streamp strm) {
if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
return Z_STREAM_ERROR;
ZFREE(strm, strm->state);
diff --git a/zlib/inffast.c b/zlib/inffast.c
index 0dbd1dbc0..d1657f3f3 100644
--- a/zlib/inffast.c
+++ b/zlib/inffast.c
@@ -1,5 +1,5 @@
/* inffast.c -- fast decoding
- * Copyright (C) 1995-2017 Mark Adler
+ * Copyright (C) 1995-2026 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -47,10 +47,7 @@
requires strm->avail_out >= 258 for each loop to avoid checking for
output space.
*/
-void ZLIB_INTERNAL inflate_fast(strm, start)
-z_streamp strm;
-unsigned start; /* inflate()'s starting value for strm->avail_out */
-{
+void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) {
struct inflate_state FAR *state;
z_const unsigned char FAR *in; /* local strm->next_in */
z_const unsigned char FAR *last; /* have enough input while in < last */
@@ -70,7 +67,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
code const FAR *dcode; /* local strm->distcode */
unsigned lmask; /* mask for first level of length codes */
unsigned dmask; /* mask for first level of distance codes */
- code here; /* retrieved table entry */
+ code const *here; /* retrieved table entry */
unsigned op; /* code bits, operation, extra bits, or */
/* window position, window bytes to copy */
unsigned len; /* match length, unused bytes */
@@ -107,20 +104,20 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
hold += (unsigned long)(*in++) << bits;
bits += 8;
}
- here = lcode[hold & lmask];
+ here = lcode + (hold & lmask);
dolen:
- op = (unsigned)(here.bits);
+ op = (unsigned)(here->bits);
hold >>= op;
bits -= op;
- op = (unsigned)(here.op);
+ op = (unsigned)(here->op);
if (op == 0) { /* literal */
- Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+ Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ?
"inflate: literal '%c'\n" :
- "inflate: literal 0x%02x\n", here.val));
- *out++ = (unsigned char)(here.val);
+ "inflate: literal 0x%02x\n", here->val));
+ *out++ = (unsigned char)(here->val);
}
else if (op & 16) { /* length base */
- len = (unsigned)(here.val);
+ len = (unsigned)(here->val);
op &= 15; /* number of extra bits */
if (op) {
if (bits < op) {
@@ -138,14 +135,14 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
hold += (unsigned long)(*in++) << bits;
bits += 8;
}
- here = dcode[hold & dmask];
+ here = dcode + (hold & dmask);
dodist:
- op = (unsigned)(here.bits);
+ op = (unsigned)(here->bits);
hold >>= op;
bits -= op;
- op = (unsigned)(here.op);
+ op = (unsigned)(here->op);
if (op & 16) { /* distance base */
- dist = (unsigned)(here.val);
+ dist = (unsigned)(here->val);
op &= 15; /* number of extra bits */
if (bits < op) {
hold += (unsigned long)(*in++) << bits;
@@ -158,7 +155,8 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
dist += (unsigned)hold & ((1U << op) - 1);
#ifdef INFLATE_STRICT
if (dist > dmax) {
- strm->msg = (char *)"invalid distance too far back";
+ strm->msg = (z_const char *)
+ "invalid distance too far back";
state->mode = BAD;
break;
}
@@ -171,8 +169,8 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
op = dist - op; /* distance back in window */
if (op > whave) {
if (state->sane) {
- strm->msg =
- (char *)"invalid distance too far back";
+ strm->msg = (z_const char *)
+ "invalid distance too far back";
state->mode = BAD;
break;
}
@@ -264,17 +262,17 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
}
}
else if ((op & 64) == 0) { /* 2nd level distance code */
- here = dcode[here.val + (hold & ((1U << op) - 1))];
+ here = dcode + here->val + (hold & ((1U << op) - 1));
goto dodist;
}
else {
- strm->msg = (char *)"invalid distance code";
+ strm->msg = (z_const char *)"invalid distance code";
state->mode = BAD;
break;
}
}
else if ((op & 64) == 0) { /* 2nd level length code */
- here = lcode[here.val + (hold & ((1U << op) - 1))];
+ here = lcode + here->val + (hold & ((1U << op) - 1));
goto dolen;
}
else if (op & 32) { /* end-of-block */
@@ -283,7 +281,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
break;
}
else {
- strm->msg = (char *)"invalid literal/length code";
+ strm->msg = (z_const char *)"invalid literal/length code";
state->mode = BAD;
break;
}
diff --git a/zlib/inffast.h b/zlib/inffast.h
index e5c1aa4ca..49c6d156c 100644
--- a/zlib/inffast.h
+++ b/zlib/inffast.h
@@ -8,4 +8,4 @@
subject to change. Applications should only use zlib.h.
*/
-void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start));
+void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start);
diff --git a/zlib/inffixed.h b/zlib/inffixed.h
index d62832776..05ce88e4f 100644
--- a/zlib/inffixed.h
+++ b/zlib/inffixed.h
@@ -1,94 +1,94 @@
- /* inffixed.h -- table for decoding fixed codes
- * Generated automatically by makefixed().
- */
+/* inffixed.h -- table for decoding fixed codes
+ * Generated automatically by makefixed().
+ */
- /* WARNING: this file should *not* be used by applications.
- It is part of the implementation of this library and is
- subject to change. Applications should only use zlib.h.
- */
+/* WARNING: this file should *not* be used by applications.
+ It is part of the implementation of this library and is
+ subject to change. Applications should only use zlib.h.
+ */
- static const code lenfix[512] = {
- {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
- {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
- {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
- {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
- {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
- {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
- {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
- {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
- {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
- {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
- {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
- {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
- {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
- {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
- {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
- {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
- {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
- {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
- {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
- {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
- {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
- {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
- {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
- {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
- {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
- {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
- {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
- {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
- {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
- {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
- {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
- {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
- {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
- {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
- {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
- {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
- {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
- {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
- {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
- {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
- {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
- {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
- {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
- {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
- {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
- {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
- {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
- {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
- {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
- {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
- {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
- {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
- {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
- {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
- {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
- {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
- {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
- {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
- {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
- {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
- {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
- {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
- {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
- {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
- {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
- {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
- {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
- {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
- {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
- {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
- {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
- {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
- {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
- {0,9,255}
- };
+static const code lenfix[512] = {
+ {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
+ {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
+ {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
+ {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
+ {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
+ {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
+ {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
+ {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
+ {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
+ {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
+ {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
+ {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
+ {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
+ {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
+ {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
+ {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
+ {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
+ {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
+ {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
+ {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
+ {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
+ {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
+ {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
+ {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
+ {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
+ {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
+ {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
+ {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
+ {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
+ {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
+ {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
+ {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
+ {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
+ {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
+ {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
+ {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
+ {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
+ {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
+ {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
+ {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
+ {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
+ {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
+ {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
+ {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
+ {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
+ {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
+ {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
+ {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
+ {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
+ {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
+ {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
+ {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
+ {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
+ {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
+ {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
+ {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
+ {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
+ {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
+ {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
+ {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
+ {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
+ {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
+ {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
+ {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
+ {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
+ {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
+ {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
+ {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
+ {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
+ {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
+ {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
+ {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
+ {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
+ {0,9,255}
+};
- static const code distfix[32] = {
- {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
- {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
- {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
- {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
- {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
- {22,5,193},{64,5,0}
- };
+static const code distfix[32] = {
+ {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
+ {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
+ {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
+ {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
+ {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
+ {22,5,193},{64,5,0}
+};
diff --git a/zlib/inflate.c b/zlib/inflate.c
index ac333e8c2..5f5d4922b 100644
--- a/zlib/inflate.c
+++ b/zlib/inflate.c
@@ -1,5 +1,5 @@
/* inflate.c -- zlib decompression
- * Copyright (C) 1995-2016 Mark Adler
+ * Copyright (C) 1995-2026 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -85,26 +85,7 @@
#include "inflate.h"
#include "inffast.h"
-#ifdef MAKEFIXED
-# ifndef BUILDFIXED
-# define BUILDFIXED
-# endif
-#endif
-
-/* function prototypes */
-local int inflateStateCheck OF((z_streamp strm));
-local void fixedtables OF((struct inflate_state FAR *state));
-local int updatewindow OF((z_streamp strm, const unsigned char FAR *end,
- unsigned copy));
-#ifdef BUILDFIXED
- void makefixed OF((void));
-#endif
-local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,
- unsigned len));
-
-local int inflateStateCheck(strm)
-z_streamp strm;
-{
+local int inflateStateCheck(z_streamp strm) {
struct inflate_state FAR *state;
if (strm == Z_NULL ||
strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
@@ -116,20 +97,20 @@ z_streamp strm;
return 0;
}
-int ZEXPORT inflateResetKeep(strm)
-z_streamp strm;
-{
+int ZEXPORT inflateResetKeep(z_streamp strm) {
struct inflate_state FAR *state;
if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state;
strm->total_in = strm->total_out = state->total = 0;
strm->msg = Z_NULL;
+ strm->data_type = 0;
if (state->wrap) /* to support ill-conceived Java test suite */
strm->adler = state->wrap & 1;
state->mode = HEAD;
state->last = 0;
state->havedict = 0;
+ state->flags = -1;
state->dmax = 32768U;
state->head = Z_NULL;
state->hold = 0;
@@ -141,9 +122,7 @@ z_streamp strm;
return Z_OK;
}
-int ZEXPORT inflateReset(strm)
-z_streamp strm;
-{
+int ZEXPORT inflateReset(z_streamp strm) {
struct inflate_state FAR *state;
if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
@@ -154,10 +133,7 @@ z_streamp strm;
return inflateResetKeep(strm);
}
-int ZEXPORT inflateReset2(strm, windowBits)
-z_streamp strm;
-int windowBits;
-{
+int ZEXPORT inflateReset2(z_streamp strm, int windowBits) {
int wrap;
struct inflate_state FAR *state;
@@ -167,6 +143,8 @@ int windowBits;
/* extract wrap request from windowBits parameter */
if (windowBits < 0) {
+ if (windowBits < -15)
+ return Z_STREAM_ERROR;
wrap = 0;
windowBits = -windowBits;
}
@@ -192,12 +170,8 @@ int windowBits;
return inflateReset(strm);
}
-int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
-z_streamp strm;
-int windowBits;
-const char *version;
-int stream_size;
-{
+int ZEXPORT inflateInit2_(z_streamp strm, int windowBits,
+ const char *version, int stream_size) {
int ret;
struct inflate_state FAR *state;
@@ -223,6 +197,7 @@ int stream_size;
state = (struct inflate_state FAR *)
ZALLOC(strm, 1, sizeof(struct inflate_state));
if (state == Z_NULL) return Z_MEM_ERROR;
+ zmemzero(state, sizeof(struct inflate_state));
Tracev((stderr, "inflate: allocated\n"));
strm->state = (struct internal_state FAR *)state;
state->strm = strm;
@@ -236,22 +211,17 @@ int stream_size;
return ret;
}
-int ZEXPORT inflateInit_(strm, version, stream_size)
-z_streamp strm;
-const char *version;
-int stream_size;
-{
+int ZEXPORT inflateInit_(z_streamp strm, const char *version,
+ int stream_size) {
return inflateInit2_(strm, DEF_WBITS, version, stream_size);
}
-int ZEXPORT inflatePrime(strm, bits, value)
-z_streamp strm;
-int bits;
-int value;
-{
+int ZEXPORT inflatePrime(z_streamp strm, int bits, int value) {
struct inflate_state FAR *state;
if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ if (bits == 0)
+ return Z_OK;
state = (struct inflate_state FAR *)strm->state;
if (bits < 0) {
state->hold = 0;
@@ -260,125 +230,11 @@ int value;
}
if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR;
value &= (1L << bits) - 1;
- state->hold += (unsigned)value << state->bits;
+ state->hold += (unsigned long)value << state->bits;
state->bits += (uInt)bits;
return Z_OK;
}
-/*
- Return state with length and distance decoding tables and index sizes set to
- fixed code decoding. Normally this returns fixed tables from inffixed.h.
- If BUILDFIXED is defined, then instead this routine builds the tables the
- first time it's called, and returns those tables the first time and
- thereafter. This reduces the size of the code by about 2K bytes, in
- exchange for a little execution time. However, BUILDFIXED should not be
- used for threaded applications, since the rewriting of the tables and virgin
- may not be thread-safe.
- */
-local void fixedtables(state)
-struct inflate_state FAR *state;
-{
-#ifdef BUILDFIXED
- static int virgin = 1;
- static code *lenfix, *distfix;
- static code fixed[544];
-
- /* build fixed huffman tables if first call (may not be thread safe) */
- if (virgin) {
- unsigned sym, bits;
- static code *next;
-
- /* literal/length table */
- sym = 0;
- while (sym < 144) state->lens[sym++] = 8;
- while (sym < 256) state->lens[sym++] = 9;
- while (sym < 280) state->lens[sym++] = 7;
- while (sym < 288) state->lens[sym++] = 8;
- next = fixed;
- lenfix = next;
- bits = 9;
- inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
-
- /* distance table */
- sym = 0;
- while (sym < 32) state->lens[sym++] = 5;
- distfix = next;
- bits = 5;
- inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
-
- /* do this just once */
- virgin = 0;
- }
-#else /* !BUILDFIXED */
-# include "inffixed.h"
-#endif /* BUILDFIXED */
- state->lencode = lenfix;
- state->lenbits = 9;
- state->distcode = distfix;
- state->distbits = 5;
-}
-
-#ifdef MAKEFIXED
-#include
-
-/*
- Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also
- defines BUILDFIXED, so the tables are built on the fly. makefixed() writes
- those tables to stdout, which would be piped to inffixed.h. A small program
- can simply call makefixed to do this:
-
- void makefixed(void);
-
- int main(void)
- {
- makefixed();
- return 0;
- }
-
- Then that can be linked with zlib built with MAKEFIXED defined and run:
-
- a.out > inffixed.h
- */
-void makefixed()
-{
- unsigned low, size;
- struct inflate_state state;
-
- fixedtables(&state);
- puts(" /* inffixed.h -- table for decoding fixed codes");
- puts(" * Generated automatically by makefixed().");
- puts(" */");
- puts("");
- puts(" /* WARNING: this file should *not* be used by applications.");
- puts(" It is part of the implementation of this library and is");
- puts(" subject to change. Applications should only use zlib.h.");
- puts(" */");
- puts("");
- size = 1U << 9;
- printf(" static const code lenfix[%u] = {", size);
- low = 0;
- for (;;) {
- if ((low % 7) == 0) printf("\n ");
- printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
- state.lencode[low].bits, state.lencode[low].val);
- if (++low == size) break;
- putchar(',');
- }
- puts("\n };");
- size = 1U << 5;
- printf("\n static const code distfix[%u] = {", size);
- low = 0;
- for (;;) {
- if ((low % 6) == 0) printf("\n ");
- printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
- state.distcode[low].val);
- if (++low == size) break;
- putchar(',');
- }
- puts("\n };");
-}
-#endif /* MAKEFIXED */
-
/*
Update the window with the last wsize (normally 32K) bytes written before
returning. If window does not exist yet, create it. This is only called
@@ -393,11 +249,7 @@ void makefixed()
output will fall in the output data, making match copies simpler and faster.
The advantage may be dependent on the size of the processor's data caches.
*/
-local int updatewindow(strm, end, copy)
-z_streamp strm;
-const Bytef *end;
-unsigned copy;
-{
+local int updatewindow(z_streamp strm, const Bytef *end, unsigned copy) {
struct inflate_state FAR *state;
unsigned dist;
@@ -447,10 +299,10 @@ unsigned copy;
/* check function to use adler32() for zlib or crc32() for gzip */
#ifdef GUNZIP
-# define UPDATE(check, buf, len) \
+# define UPDATE_CHECK(check, buf, len) \
(state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
#else
-# define UPDATE(check, buf, len) adler32(check, buf, len)
+# define UPDATE_CHECK(check, buf, len) adler32(check, buf, len)
#endif
/* check macros for header crc */
@@ -619,10 +471,7 @@ unsigned copy;
will return Z_BUF_ERROR if it has not reached the end of the stream.
*/
-int ZEXPORT inflate(strm, flush)
-z_streamp strm;
-int flush;
-{
+int ZEXPORT inflate(z_streamp strm, int flush) {
struct inflate_state FAR *state;
z_const unsigned char FAR *next; /* next input */
unsigned char FAR *put; /* next output */
@@ -670,7 +519,6 @@ int flush;
state->mode = FLAGS;
break;
}
- state->flags = 0; /* expect zlib header */
if (state->head != Z_NULL)
state->head->done = -1;
if (!(state->wrap & 1) || /* check if zlib header allowed */
@@ -678,12 +526,12 @@ int flush;
if (
#endif
((BITS(8) << 8) + (hold >> 8)) % 31) {
- strm->msg = (char *)"incorrect header check";
+ strm->msg = (z_const char *)"incorrect header check";
state->mode = BAD;
break;
}
if (BITS(4) != Z_DEFLATED) {
- strm->msg = (char *)"unknown compression method";
+ strm->msg = (z_const char *)"unknown compression method";
state->mode = BAD;
break;
}
@@ -692,11 +540,12 @@ int flush;
if (state->wbits == 0)
state->wbits = len;
if (len > 15 || len > state->wbits) {
- strm->msg = (char *)"invalid window size";
+ strm->msg = (z_const char *)"invalid window size";
state->mode = BAD;
break;
}
state->dmax = 1U << len;
+ state->flags = 0; /* indicate zlib header */
Tracev((stderr, "inflate: zlib header ok\n"));
strm->adler = state->check = adler32(0L, Z_NULL, 0);
state->mode = hold & 0x200 ? DICTID : TYPE;
@@ -707,12 +556,12 @@ int flush;
NEEDBITS(16);
state->flags = (int)(hold);
if ((state->flags & 0xff) != Z_DEFLATED) {
- strm->msg = (char *)"unknown compression method";
+ strm->msg = (z_const char *)"unknown compression method";
state->mode = BAD;
break;
}
if (state->flags & 0xe000) {
- strm->msg = (char *)"unknown header flags set";
+ strm->msg = (z_const char *)"unknown header flags set";
state->mode = BAD;
break;
}
@@ -722,6 +571,7 @@ int flush;
CRC2(state->check, hold);
INITBITS();
state->mode = TIME;
+ /* fallthrough */
case TIME:
NEEDBITS(32);
if (state->head != Z_NULL)
@@ -730,6 +580,7 @@ int flush;
CRC4(state->check, hold);
INITBITS();
state->mode = OS;
+ /* fallthrough */
case OS:
NEEDBITS(16);
if (state->head != Z_NULL) {
@@ -740,6 +591,7 @@ int flush;
CRC2(state->check, hold);
INITBITS();
state->mode = EXLEN;
+ /* fallthrough */
case EXLEN:
if (state->flags & 0x0400) {
NEEDBITS(16);
@@ -753,14 +605,16 @@ int flush;
else if (state->head != Z_NULL)
state->head->extra = Z_NULL;
state->mode = EXTRA;
+ /* fallthrough */
case EXTRA:
if (state->flags & 0x0400) {
copy = state->length;
if (copy > have) copy = have;
if (copy) {
if (state->head != Z_NULL &&
- state->head->extra != Z_NULL) {
- len = state->head->extra_len - state->length;
+ state->head->extra != Z_NULL &&
+ (len = state->head->extra_len - state->length) <
+ state->head->extra_max) {
zmemcpy(state->head->extra + len, next,
len + copy > state->head->extra_max ?
state->head->extra_max - len : copy);
@@ -775,6 +629,7 @@ int flush;
}
state->length = 0;
state->mode = NAME;
+ /* fallthrough */
case NAME:
if (state->flags & 0x0800) {
if (have == 0) goto inf_leave;
@@ -796,6 +651,7 @@ int flush;
state->head->name = Z_NULL;
state->length = 0;
state->mode = COMMENT;
+ /* fallthrough */
case COMMENT:
if (state->flags & 0x1000) {
if (have == 0) goto inf_leave;
@@ -816,11 +672,12 @@ int flush;
else if (state->head != Z_NULL)
state->head->comment = Z_NULL;
state->mode = HCRC;
+ /* fallthrough */
case HCRC:
if (state->flags & 0x0200) {
NEEDBITS(16);
if ((state->wrap & 4) && hold != (state->check & 0xffff)) {
- strm->msg = (char *)"header crc mismatch";
+ strm->msg = (z_const char *)"header crc mismatch";
state->mode = BAD;
break;
}
@@ -839,6 +696,7 @@ int flush;
strm->adler = state->check = ZSWAP32(hold);
INITBITS();
state->mode = DICT;
+ /* fallthrough */
case DICT:
if (state->havedict == 0) {
RESTORE();
@@ -846,8 +704,10 @@ int flush;
}
strm->adler = state->check = adler32(0L, Z_NULL, 0);
state->mode = TYPE;
+ /* fallthrough */
case TYPE:
if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
+ /* fallthrough */
case TYPEDO:
if (state->last) {
BYTEBITS();
@@ -864,7 +724,7 @@ int flush;
state->mode = STORED;
break;
case 1: /* fixed block */
- fixedtables(state);
+ inflate_fixed(state);
Tracev((stderr, "inflate: fixed codes block%s\n",
state->last ? " (last)" : ""));
state->mode = LEN_; /* decode codes */
@@ -878,8 +738,8 @@ int flush;
state->last ? " (last)" : ""));
state->mode = TABLE;
break;
- case 3:
- strm->msg = (char *)"invalid block type";
+ default:
+ strm->msg = (z_const char *)"invalid block type";
state->mode = BAD;
}
DROPBITS(2);
@@ -888,7 +748,7 @@ int flush;
BYTEBITS(); /* go to byte boundary */
NEEDBITS(32);
if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
- strm->msg = (char *)"invalid stored block lengths";
+ strm->msg = (z_const char *)"invalid stored block lengths";
state->mode = BAD;
break;
}
@@ -898,8 +758,10 @@ int flush;
INITBITS();
state->mode = COPY_;
if (flush == Z_TREES) goto inf_leave;
+ /* fallthrough */
case COPY_:
state->mode = COPY;
+ /* fallthrough */
case COPY:
copy = state->length;
if (copy) {
@@ -927,7 +789,8 @@ int flush;
DROPBITS(4);
#ifndef PKZIP_BUG_WORKAROUND
if (state->nlen > 286 || state->ndist > 30) {
- strm->msg = (char *)"too many length or distance symbols";
+ strm->msg = (z_const char *)
+ "too many length or distance symbols";
state->mode = BAD;
break;
}
@@ -935,6 +798,7 @@ int flush;
Tracev((stderr, "inflate: table sizes ok\n"));
state->have = 0;
state->mode = LENLENS;
+ /* fallthrough */
case LENLENS:
while (state->have < state->ncode) {
NEEDBITS(3);
@@ -944,18 +808,19 @@ int flush;
while (state->have < 19)
state->lens[order[state->have++]] = 0;
state->next = state->codes;
- state->lencode = (const code FAR *)(state->next);
+ state->lencode = state->distcode = (const code FAR *)(state->next);
state->lenbits = 7;
ret = inflate_table(CODES, state->lens, 19, &(state->next),
&(state->lenbits), state->work);
if (ret) {
- strm->msg = (char *)"invalid code lengths set";
+ strm->msg = (z_const char *)"invalid code lengths set";
state->mode = BAD;
break;
}
Tracev((stderr, "inflate: code lengths ok\n"));
state->have = 0;
state->mode = CODELENS;
+ /* fallthrough */
case CODELENS:
while (state->have < state->nlen + state->ndist) {
for (;;) {
@@ -972,7 +837,8 @@ int flush;
NEEDBITS(here.bits + 2);
DROPBITS(here.bits);
if (state->have == 0) {
- strm->msg = (char *)"invalid bit length repeat";
+ strm->msg = (z_const char *)
+ "invalid bit length repeat";
state->mode = BAD;
break;
}
@@ -995,7 +861,8 @@ int flush;
DROPBITS(7);
}
if (state->have + copy > state->nlen + state->ndist) {
- strm->msg = (char *)"invalid bit length repeat";
+ strm->msg = (z_const char *)
+ "invalid bit length repeat";
state->mode = BAD;
break;
}
@@ -1009,7 +876,8 @@ int flush;
/* check for end-of-block code (better have one) */
if (state->lens[256] == 0) {
- strm->msg = (char *)"invalid code -- missing end-of-block";
+ strm->msg = (z_const char *)
+ "invalid code -- missing end-of-block";
state->mode = BAD;
break;
}
@@ -1023,7 +891,7 @@ int flush;
ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
&(state->lenbits), state->work);
if (ret) {
- strm->msg = (char *)"invalid literal/lengths set";
+ strm->msg = (z_const char *)"invalid literal/lengths set";
state->mode = BAD;
break;
}
@@ -1032,15 +900,17 @@ int flush;
ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
&(state->next), &(state->distbits), state->work);
if (ret) {
- strm->msg = (char *)"invalid distances set";
+ strm->msg = (z_const char *)"invalid distances set";
state->mode = BAD;
break;
}
Tracev((stderr, "inflate: codes ok\n"));
state->mode = LEN_;
if (flush == Z_TREES) goto inf_leave;
+ /* fallthrough */
case LEN_:
state->mode = LEN;
+ /* fallthrough */
case LEN:
if (have >= 6 && left >= 258) {
RESTORE();
@@ -1084,12 +954,13 @@ int flush;
break;
}
if (here.op & 64) {
- strm->msg = (char *)"invalid literal/length code";
+ strm->msg = (z_const char *)"invalid literal/length code";
state->mode = BAD;
break;
}
state->extra = (unsigned)(here.op) & 15;
state->mode = LENEXT;
+ /* fallthrough */
case LENEXT:
if (state->extra) {
NEEDBITS(state->extra);
@@ -1100,6 +971,7 @@ int flush;
Tracevv((stderr, "inflate: length %u\n", state->length));
state->was = state->length;
state->mode = DIST;
+ /* fallthrough */
case DIST:
for (;;) {
here = state->distcode[BITS(state->distbits)];
@@ -1120,13 +992,14 @@ int flush;
DROPBITS(here.bits);
state->back += here.bits;
if (here.op & 64) {
- strm->msg = (char *)"invalid distance code";
+ strm->msg = (z_const char *)"invalid distance code";
state->mode = BAD;
break;
}
state->offset = (unsigned)here.val;
state->extra = (unsigned)(here.op) & 15;
state->mode = DISTEXT;
+ /* fallthrough */
case DISTEXT:
if (state->extra) {
NEEDBITS(state->extra);
@@ -1136,13 +1009,14 @@ int flush;
}
#ifdef INFLATE_STRICT
if (state->offset > state->dmax) {
- strm->msg = (char *)"invalid distance too far back";
+ strm->msg = (z_const char *)"invalid distance too far back";
state->mode = BAD;
break;
}
#endif
Tracevv((stderr, "inflate: distance %u\n", state->offset));
state->mode = MATCH;
+ /* fallthrough */
case MATCH:
if (left == 0) goto inf_leave;
copy = out - left;
@@ -1150,7 +1024,8 @@ int flush;
copy = state->offset - copy;
if (copy > state->whave) {
if (state->sane) {
- strm->msg = (char *)"invalid distance too far back";
+ strm->msg = (z_const char *)
+ "invalid distance too far back";
state->mode = BAD;
break;
}
@@ -1202,14 +1077,14 @@ int flush;
state->total += out;
if ((state->wrap & 4) && out)
strm->adler = state->check =
- UPDATE(state->check, put - out, out);
+ UPDATE_CHECK(state->check, put - out, out);
out = left;
if ((state->wrap & 4) && (
#ifdef GUNZIP
state->flags ? hold :
#endif
ZSWAP32(hold)) != state->check) {
- strm->msg = (char *)"incorrect data check";
+ strm->msg = (z_const char *)"incorrect data check";
state->mode = BAD;
break;
}
@@ -1218,11 +1093,12 @@ int flush;
}
#ifdef GUNZIP
state->mode = LENGTH;
+ /* fallthrough */
case LENGTH:
if (state->wrap && state->flags) {
NEEDBITS(32);
- if (hold != (state->total & 0xffffffffUL)) {
- strm->msg = (char *)"incorrect length check";
+ if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) {
+ strm->msg = (z_const char *)"incorrect length check";
state->mode = BAD;
break;
}
@@ -1231,6 +1107,7 @@ int flush;
}
#endif
state->mode = DONE;
+ /* fallthrough */
case DONE:
ret = Z_STREAM_END;
goto inf_leave;
@@ -1240,6 +1117,7 @@ int flush;
case MEM:
return Z_MEM_ERROR;
case SYNC:
+ /* fallthrough */
default:
return Z_STREAM_ERROR;
}
@@ -1265,7 +1143,7 @@ int flush;
state->total += out;
if ((state->wrap & 4) && out)
strm->adler = state->check =
- UPDATE(state->check, strm->next_out - out, out);
+ UPDATE_CHECK(state->check, strm->next_out - out, out);
strm->data_type = (int)state->bits + (state->last ? 64 : 0) +
(state->mode == TYPE ? 128 : 0) +
(state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
@@ -1274,9 +1152,7 @@ int flush;
return ret;
}
-int ZEXPORT inflateEnd(strm)
-z_streamp strm;
-{
+int ZEXPORT inflateEnd(z_streamp strm) {
struct inflate_state FAR *state;
if (inflateStateCheck(strm))
return Z_STREAM_ERROR;
@@ -1288,11 +1164,8 @@ z_streamp strm;
return Z_OK;
}
-int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength)
-z_streamp strm;
-Bytef *dictionary;
-uInt *dictLength;
-{
+int ZEXPORT inflateGetDictionary(z_streamp strm, Bytef *dictionary,
+ uInt *dictLength) {
struct inflate_state FAR *state;
/* check state */
@@ -1311,11 +1184,8 @@ uInt *dictLength;
return Z_OK;
}
-int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
-z_streamp strm;
-const Bytef *dictionary;
-uInt dictLength;
-{
+int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary,
+ uInt dictLength) {
struct inflate_state FAR *state;
unsigned long dictid;
int ret;
@@ -1346,10 +1216,7 @@ uInt dictLength;
return Z_OK;
}
-int ZEXPORT inflateGetHeader(strm, head)
-z_streamp strm;
-gz_headerp head;
-{
+int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head) {
struct inflate_state FAR *state;
/* check state */
@@ -1374,11 +1241,8 @@ gz_headerp head;
called again with more data and the *have state. *have is initialized to
zero for the first call.
*/
-local unsigned syncsearch(have, buf, len)
-unsigned FAR *have;
-const unsigned char FAR *buf;
-unsigned len;
-{
+local unsigned syncsearch(unsigned FAR *have, const unsigned char FAR *buf,
+ unsigned len) {
unsigned got;
unsigned next;
@@ -1397,10 +1261,9 @@ unsigned len;
return next;
}
-int ZEXPORT inflateSync(strm)
-z_streamp strm;
-{
+int ZEXPORT inflateSync(z_streamp strm) {
unsigned len; /* number of bytes to look at or looked at */
+ int flags; /* temporary to save header status */
unsigned long in, out; /* temporary to save total_in and total_out */
unsigned char buf[4]; /* to restore bit buffer to byte string */
struct inflate_state FAR *state;
@@ -1413,7 +1276,7 @@ z_streamp strm;
/* if first time, start search in bit buffer */
if (state->mode != SYNC) {
state->mode = SYNC;
- state->hold <<= state->bits & 7;
+ state->hold >>= state->bits & 7;
state->bits -= state->bits & 7;
len = 0;
while (state->bits >= 8) {
@@ -1433,9 +1296,15 @@ z_streamp strm;
/* return no joy or set up to restart inflate() on a new block */
if (state->have != 4) return Z_DATA_ERROR;
+ if (state->flags == -1)
+ state->wrap = 0; /* if no header yet, treat as raw */
+ else
+ state->wrap &= ~4; /* no point in computing a check value now */
+ flags = state->flags;
in = strm->total_in; out = strm->total_out;
inflateReset(strm);
strm->total_in = in; strm->total_out = out;
+ state->flags = flags;
state->mode = TYPE;
return Z_OK;
}
@@ -1448,9 +1317,7 @@ z_streamp strm;
block. When decompressing, PPP checks that at the end of input packet,
inflate is waiting for these length bytes.
*/
-int ZEXPORT inflateSyncPoint(strm)
-z_streamp strm;
-{
+int ZEXPORT inflateSyncPoint(z_streamp strm) {
struct inflate_state FAR *state;
if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
@@ -1458,14 +1325,10 @@ z_streamp strm;
return state->mode == STORED && state->bits == 0;
}
-int ZEXPORT inflateCopy(dest, source)
-z_streamp dest;
-z_streamp source;
-{
+int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) {
struct inflate_state FAR *state;
struct inflate_state FAR *copy;
unsigned char FAR *window;
- unsigned wsize;
/* check input */
if (inflateStateCheck(source) || dest == Z_NULL)
@@ -1476,6 +1339,7 @@ z_streamp source;
copy = (struct inflate_state FAR *)
ZALLOC(source, 1, sizeof(struct inflate_state));
if (copy == Z_NULL) return Z_MEM_ERROR;
+ zmemzero(copy, sizeof(struct inflate_state));
window = Z_NULL;
if (state->window != Z_NULL) {
window = (unsigned char FAR *)
@@ -1487,8 +1351,8 @@ z_streamp source;
}
/* copy state */
- zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
- zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
+ zmemcpy(dest, source, sizeof(z_stream));
+ zmemcpy(copy, state, sizeof(struct inflate_state));
copy->strm = dest;
if (state->lencode >= state->codes &&
state->lencode <= state->codes + ENOUGH - 1) {
@@ -1496,19 +1360,14 @@ z_streamp source;
copy->distcode = copy->codes + (state->distcode - state->codes);
}
copy->next = copy->codes + (state->next - state->codes);
- if (window != Z_NULL) {
- wsize = 1U << state->wbits;
- zmemcpy(window, state->window, wsize);
- }
+ if (window != Z_NULL)
+ zmemcpy(window, state->window, state->whave);
copy->window = window;
dest->state = (struct internal_state FAR *)copy;
return Z_OK;
}
-int ZEXPORT inflateUndermine(strm, subvert)
-z_streamp strm;
-int subvert;
-{
+int ZEXPORT inflateUndermine(z_streamp strm, int subvert) {
struct inflate_state FAR *state;
if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
@@ -1523,24 +1382,19 @@ int subvert;
#endif
}
-int ZEXPORT inflateValidate(strm, check)
-z_streamp strm;
-int check;
-{
+int ZEXPORT inflateValidate(z_streamp strm, int check) {
struct inflate_state FAR *state;
if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state;
- if (check)
+ if (check && state->wrap)
state->wrap |= 4;
else
state->wrap &= ~4;
return Z_OK;
}
-long ZEXPORT inflateMark(strm)
-z_streamp strm;
-{
+long ZEXPORT inflateMark(z_streamp strm) {
struct inflate_state FAR *state;
if (inflateStateCheck(strm))
@@ -1551,9 +1405,7 @@ z_streamp strm;
(state->mode == MATCH ? state->was - state->length : 0));
}
-unsigned long ZEXPORT inflateCodesUsed(strm)
-z_streamp strm;
-{
+unsigned long ZEXPORT inflateCodesUsed(z_streamp strm) {
struct inflate_state FAR *state;
if (inflateStateCheck(strm)) return (unsigned long)-1;
state = (struct inflate_state FAR *)strm->state;
diff --git a/zlib/inflate.h b/zlib/inflate.h
index a46cce6b6..f758e0dcc 100644
--- a/zlib/inflate.h
+++ b/zlib/inflate.h
@@ -1,5 +1,5 @@
/* inflate.h -- internal inflate state definition
- * Copyright (C) 1995-2016 Mark Adler
+ * Copyright (C) 1995-2019 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -86,7 +86,8 @@ struct inflate_state {
int wrap; /* bit 0 true for zlib, bit 1 true for gzip,
bit 2 true to validate check value */
int havedict; /* true if dictionary provided */
- int flags; /* gzip header method and flags (0 if zlib) */
+ int flags; /* gzip header method and flags, 0 if zlib, or
+ -1 if raw or no header yet */
unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
unsigned long check; /* protected copy of check value */
unsigned long total; /* protected copy of output count */
@@ -99,7 +100,7 @@ struct inflate_state {
unsigned char FAR *window; /* allocated sliding window, if needed */
/* bit accumulator */
unsigned long hold; /* input bit accumulator */
- unsigned bits; /* number of bits in "in" */
+ unsigned bits; /* number of bits in hold */
/* for string and stored block copying */
unsigned length; /* literal or length of data to copy */
unsigned offset; /* distance back to copy string from */
diff --git a/zlib/inftrees.c b/zlib/inftrees.c
index 2ea08fc13..dcbc64e05 100644
--- a/zlib/inftrees.c
+++ b/zlib/inftrees.c
@@ -1,15 +1,29 @@
/* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-2017 Mark Adler
+ * Copyright (C) 1995-2026 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
+#ifdef MAKEFIXED
+# ifndef BUILDFIXED
+# define BUILDFIXED
+# endif
+#endif
+#ifdef BUILDFIXED
+# define Z_ONCE
+#endif
+
#include "zutil.h"
#include "inftrees.h"
+#include "inflate.h"
+
+#ifndef NULL
+# define NULL 0
+#endif
#define MAXBITS 15
const char inflate_copyright[] =
- " inflate 1.2.11 Copyright 1995-2017 Mark Adler ";
+ " inflate 1.3.2 Copyright 1995-2026 Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
@@ -29,14 +43,9 @@ const char inflate_copyright[] =
table index bits. It will differ if the request is greater than the
longest code or if it is less than the shortest code.
*/
-int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work)
-codetype type;
-unsigned short FAR *lens;
-unsigned codes;
-code FAR * FAR *table;
-unsigned FAR *bits;
-unsigned short FAR *work;
-{
+int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
+ unsigned codes, code FAR * FAR *table,
+ unsigned FAR *bits, unsigned short FAR *work) {
unsigned len; /* a code's length in bits */
unsigned sym; /* index of code symbols */
unsigned min, max; /* minimum and maximum code lengths */
@@ -52,9 +61,9 @@ unsigned short FAR *work;
unsigned mask; /* mask for low root bits */
code here; /* table entry for duplication */
code FAR *next; /* next available space in table */
- const unsigned short FAR *base; /* base value table to use */
- const unsigned short FAR *extra; /* extra bits table to use */
- unsigned match; /* use base and extra for symbol >= match */
+ const unsigned short FAR *base = NULL; /* base value table to use */
+ const unsigned short FAR *extra = NULL; /* extra bits table to use */
+ unsigned match = 0; /* use base and extra for symbol >= match */
unsigned short count[MAXBITS+1]; /* number of codes of each length */
unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
static const unsigned short lbase[31] = { /* Length codes 257..285 base */
@@ -62,7 +71,7 @@ unsigned short FAR *work;
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
- 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202};
+ 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 199, 75};
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
@@ -180,7 +189,6 @@ unsigned short FAR *work;
/* set up for code type */
switch (type) {
case CODES:
- base = extra = work; /* dummy value--not used */
match = 20;
break;
case LENS:
@@ -188,10 +196,9 @@ unsigned short FAR *work;
extra = lext;
match = 257;
break;
- default: /* DISTS */
+ case DISTS:
base = dbase;
extra = dext;
- match = 0;
}
/* initialize state for loop */
@@ -302,3 +309,116 @@ unsigned short FAR *work;
*bits = root;
return 0;
}
+
+#ifdef BUILDFIXED
+/*
+ If this is compiled with BUILDFIXED defined, and if inflate will be used in
+ multiple threads, and if atomics are not available, then inflate() must be
+ called with a fixed block (e.g. 0x03 0x00) to initialize the tables and must
+ return before any other threads are allowed to call inflate.
+ */
+
+static code *lenfix, *distfix;
+static code fixed[544];
+
+/* State for z_once(). */
+local z_once_t built = Z_ONCE_INIT;
+
+local void buildtables(void) {
+ unsigned sym, bits;
+ static code *next;
+ unsigned short lens[288], work[288];
+
+ /* literal/length table */
+ sym = 0;
+ while (sym < 144) lens[sym++] = 8;
+ while (sym < 256) lens[sym++] = 9;
+ while (sym < 280) lens[sym++] = 7;
+ while (sym < 288) lens[sym++] = 8;
+ next = fixed;
+ lenfix = next;
+ bits = 9;
+ inflate_table(LENS, lens, 288, &(next), &(bits), work);
+
+ /* distance table */
+ sym = 0;
+ while (sym < 32) lens[sym++] = 5;
+ distfix = next;
+ bits = 5;
+ inflate_table(DISTS, lens, 32, &(next), &(bits), work);
+}
+#else /* !BUILDFIXED */
+# include "inffixed.h"
+#endif /* BUILDFIXED */
+
+/*
+ Return state with length and distance decoding tables and index sizes set to
+ fixed code decoding. Normally this returns fixed tables from inffixed.h.
+ If BUILDFIXED is defined, then instead this routine builds the tables the
+ first time it's called, and returns those tables the first time and
+ thereafter. This reduces the size of the code by about 2K bytes, in
+ exchange for a little execution time. However, BUILDFIXED should not be
+ used for threaded applications if atomics are not available, as it will
+ not be thread-safe.
+ */
+void inflate_fixed(struct inflate_state FAR *state) {
+#ifdef BUILDFIXED
+ z_once(&built, buildtables);
+#endif /* BUILDFIXED */
+ state->lencode = lenfix;
+ state->lenbits = 9;
+ state->distcode = distfix;
+ state->distbits = 5;
+}
+
+#ifdef MAKEFIXED
+#include
+
+/*
+ Write out the inffixed.h that will be #include'd above. Defining MAKEFIXED
+ also defines BUILDFIXED, so the tables are built on the fly. main() writes
+ those tables to stdout, which would directed to inffixed.h. Compile this
+ along with zutil.c:
+
+ cc -DMAKEFIXED -o fix inftrees.c zutil.c
+ ./fix > inffixed.h
+ */
+int main(void) {
+ unsigned low, size;
+ struct inflate_state state;
+
+ inflate_fixed(&state);
+ puts("/* inffixed.h -- table for decoding fixed codes");
+ puts(" * Generated automatically by makefixed().");
+ puts(" */");
+ puts("");
+ puts("/* WARNING: this file should *not* be used by applications.");
+ puts(" It is part of the implementation of this library and is");
+ puts(" subject to change. Applications should only use zlib.h.");
+ puts(" */");
+ puts("");
+ size = 1U << 9;
+ printf("static const code lenfix[%u] = {", size);
+ low = 0;
+ for (;;) {
+ if ((low % 7) == 0) printf("\n ");
+ printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
+ state.lencode[low].bits, state.lencode[low].val);
+ if (++low == size) break;
+ putchar(',');
+ }
+ puts("\n};");
+ size = 1U << 5;
+ printf("\nstatic const code distfix[%u] = {", size);
+ low = 0;
+ for (;;) {
+ if ((low % 6) == 0) printf("\n ");
+ printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
+ state.distcode[low].val);
+ if (++low == size) break;
+ putchar(',');
+ }
+ puts("\n};");
+ return 0;
+}
+#endif /* MAKEFIXED */
diff --git a/zlib/inftrees.h b/zlib/inftrees.h
index baa53a0b1..84d053697 100644
--- a/zlib/inftrees.h
+++ b/zlib/inftrees.h
@@ -1,5 +1,5 @@
/* inftrees.h -- header to use inftrees.c
- * Copyright (C) 1995-2005, 2010 Mark Adler
+ * Copyright (C) 1995-2026 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -38,11 +38,11 @@ typedef struct {
/* Maximum size of the dynamic table. The maximum number of code structures is
1444, which is the sum of 852 for literal/length codes and 592 for distance
codes. These values were found by exhaustive searches using the program
- examples/enough.c found in the zlib distribtution. The arguments to that
+ examples/enough.c found in the zlib distribution. The arguments to that
program are the number of symbols, the initial root table size, and the
maximum bit length of a code. "enough 286 9 15" for literal/length codes
- returns returns 852, and "enough 30 6 15" for distance codes returns 592.
- The initial root table size (9 or 6) is found in the fifth argument of the
+ returns 852, and "enough 30 6 15" for distance codes returns 592. The
+ initial root table size (9 or 6) is found in the fifth argument of the
inflate_table() calls in inflate.c and infback.c. If the root table size is
changed, then these maximum sizes would be need to be recalculated and
updated. */
@@ -57,6 +57,8 @@ typedef enum {
DISTS
} codetype;
-int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens,
- unsigned codes, code FAR * FAR *table,
- unsigned FAR *bits, unsigned short FAR *work));
+int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
+ unsigned codes, code FAR * FAR *table,
+ unsigned FAR *bits, unsigned short FAR *work);
+struct inflate_state;
+void ZLIB_INTERNAL inflate_fixed(struct inflate_state FAR *state);
diff --git a/zlib/make_vms.com b/zlib/make_vms.com
index 65e9d0cbc..4dc8a8913 100644
--- a/zlib/make_vms.com
+++ b/zlib/make_vms.com
@@ -14,9 +14,9 @@ $! 0.02 20061008 Adapt to new Makefile.in
$! 0.03 20091224 Add support for large file check
$! 0.04 20100110 Add new gzclose, gzlib, gzread, gzwrite
$! 0.05 20100221 Exchange zlibdefs.h by zconf.h.in
-$! 0.06 20120111 Fix missing amiss_err, update zconf_h.in, fix new exmples
+$! 0.06 20120111 Fix missing amiss_err, update zconf_h.in, fix new examples
$! subdir path, update module search in makefile.in
-$! 0.07 20120115 Triggered by work done by Alexey Chupahin completly redesigned
+$! 0.07 20120115 Triggered by work done by Alexey Chupahin completely redesigned
$! shared image creation
$! 0.08 20120219 Make it work on VAX again, pre-load missing symbols to shared
$! image
diff --git a/zlib/msdos/Makefile.dj2 b/zlib/msdos/Makefile.dj2
index 29b03954d..c8dc3ceaa 100644
--- a/zlib/msdos/Makefile.dj2
+++ b/zlib/msdos/Makefile.dj2
@@ -29,8 +29,8 @@ CC=gcc
#CFLAGS=-MMD -O
#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
-#CFLAGS=-MMD -g -DDEBUG
-CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
+#CFLAGS=-MMD -g -DZLIB_DEBUG
+CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith \
-Wstrict-prototypes -Wmissing-prototypes
# If cp.exe is available, replace "copy /Y" with "cp -fp" .
diff --git a/zlib/msdos/Makefile.emx b/zlib/msdos/Makefile.emx
index 9c1b57a58..e30f67bed 100644
--- a/zlib/msdos/Makefile.emx
+++ b/zlib/msdos/Makefile.emx
@@ -11,7 +11,7 @@ CC=gcc
#CFLAGS=-MMD -O
#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
-#CFLAGS=-MMD -g -DDEBUG
+#CFLAGS=-MMD -g -DZLIB_DEBUG
CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
-Wstrict-prototypes -Wmissing-prototypes
diff --git a/zlib/names.h b/zlib/names.h
index a3ae764d1..771a1d19d 100644
--- a/zlib/names.h
+++ b/zlib/names.h
@@ -17,13 +17,20 @@
#define adler32_z act_z_adler32_z
#define compress act_z_compress
#define compress2 act_z_compress2
+#define compress_z act_z_compress_z
+#define compress2_z act_z_compress2_z
#define compressBound act_z_compressBound
+#define compressBound_z act_z_compressBound_z
#define crc32 act_z_crc32
#define crc32_combine act_z_crc32_combine
#define crc32_combine64 act_z_crc32_combine64
+#define crc32_combine_gen act_z_crc32_combine_gen
+#define crc32_combine_gen64 act_z_crc32_combine_gen64
+#define crc32_combine_op act_z_crc32_combine_op
#define crc32_z act_z_crc32_z
#define deflate act_z_deflate
#define deflateBound act_z_deflateBound
+#define deflateBound_z act_z_deflateBound_z
#define deflateCopy act_z_deflateCopy
#define deflateEnd act_z_deflateEnd
#define deflateGetDictionary act_z_deflateGetDictionary
@@ -39,6 +46,7 @@
#define deflateSetDictionary act_z_deflateSetDictionary
#define deflateSetHeader act_z_deflateSetHeader
#define deflateTune act_z_deflateTune
+#define deflateUsed act_z_deflateUsed
#define deflate_copyright act_z_deflate_copyright
#define get_crc_table act_z_get_crc_table
#define gz_error act_z_gz_error
@@ -104,8 +112,11 @@
#define inflate_copyright act_z_inflate_copyright
#define inflate_fast act_z_inflate_fast
#define inflate_table act_z_inflate_table
+#define inflate_fixed act_z_inflate_fixed
#define uncompress act_z_uncompress
#define uncompress2 act_z_uncompress2
+#define uncompress_z act_z_uncompress_z
+#define uncompress2_z act_z_uncompress2_z
#define zError act_z_zError
#define zcalloc act_z_zcalloc
#define zcfree act_z_zcfree
diff --git a/zlib/qnx/package.qpg b/zlib/qnx/package.qpg
index aebf6e3ac..82d65f4bb 100644
--- a/zlib/qnx/package.qpg
+++ b/zlib/qnx/package.qpg
@@ -25,10 +25,10 @@
-
-
-
-
+
+
+
+
@@ -58,12 +58,12 @@
A massively spiffy yet delicately unobtrusive compression library.
zlib is designed to be a free, general-purpose, legally unencumbered, lossless data compression library for use on virtually any computer hardware and operating system.
- http://www.gzip.org/zlib
+ https://zlib.net/
- 1.2.8
+ 1.3.2
Medium
Stable
diff --git a/zlib/test/example.c b/zlib/test/example.c
index 138a699bd..9cc5f763b 100644
--- a/zlib/test/example.c
+++ b/zlib/test/example.c
@@ -1,10 +1,14 @@
/* example.c -- usage example of the zlib compression library
- * Copyright (C) 1995-2006, 2011 Jean-loup Gailly.
+ * Copyright (C) 1995-2026 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
+#if defined(_WIN32) && !defined(_CRT_SECURE_NO_WARNINGS)
+# define _CRT_SECURE_NO_WARNINGS
+#endif
+
#include "zlib.h"
#include
@@ -13,8 +17,10 @@
# include
#endif
-#if defined(VMS) || defined(RISCOS)
+#if defined(VMS)
# define TESTFILE "foo-gz"
+#elif defined(__riscos) && !defined(__TARGET_UNIXLIB__)
+# define TESTFILE "foo/gz"
#else
# define TESTFILE "foo.gz"
#endif
@@ -26,46 +32,23 @@
} \
}
-z_const char hello[] = "hello, hello!";
+static z_const char hello[] = "hello, hello!";
/* "hello world" would be more standard, but the repeated "hello"
* stresses the compression code better, sorry...
*/
-const char dictionary[] = "hello";
-uLong dictId; /* Adler32 value of the dictionary */
-
-void test_deflate OF((Byte *compr, uLong comprLen));
-void test_inflate OF((Byte *compr, uLong comprLen,
- Byte *uncompr, uLong uncomprLen));
-void test_large_deflate OF((Byte *compr, uLong comprLen,
- Byte *uncompr, uLong uncomprLen));
-void test_large_inflate OF((Byte *compr, uLong comprLen,
- Byte *uncompr, uLong uncomprLen));
-void test_flush OF((Byte *compr, uLong *comprLen));
-void test_sync OF((Byte *compr, uLong comprLen,
- Byte *uncompr, uLong uncomprLen));
-void test_dict_deflate OF((Byte *compr, uLong comprLen));
-void test_dict_inflate OF((Byte *compr, uLong comprLen,
- Byte *uncompr, uLong uncomprLen));
-int main OF((int argc, char *argv[]));
-
+static const char dictionary[] = "hello";
+static uLong dictId; /* Adler32 value of the dictionary */
#ifdef Z_SOLO
-void *myalloc OF((void *, unsigned, unsigned));
-void myfree OF((void *, void *));
-
-void *myalloc(q, n, m)
- void *q;
- unsigned n, m;
-{
- q = Z_NULL;
+static void *myalloc(void *q, unsigned n, unsigned m) {
+ (void)q;
return calloc(n, m);
}
-void myfree(void *q, void *p)
-{
- q = Z_NULL;
+static void myfree(void *q, void *p) {
+ (void)q;
free(p);
}
@@ -77,18 +60,11 @@ static free_func zfree = myfree;
static alloc_func zalloc = (alloc_func)0;
static free_func zfree = (free_func)0;
-void test_compress OF((Byte *compr, uLong comprLen,
- Byte *uncompr, uLong uncomprLen));
-void test_gzio OF((const char *fname,
- Byte *uncompr, uLong uncomprLen));
-
/* ===========================================================================
* Test compress() and uncompress()
*/
-void test_compress(compr, comprLen, uncompr, uncomprLen)
- Byte *compr, *uncompr;
- uLong comprLen, uncomprLen;
-{
+static void test_compress(Byte *compr, uLong comprLen, Byte *uncompr,
+ uLong uncomprLen) {
int err;
uLong len = (uLong)strlen(hello)+1;
@@ -111,11 +87,7 @@ void test_compress(compr, comprLen, uncompr, uncomprLen)
/* ===========================================================================
* Test read/write of .gz files
*/
-void test_gzio(fname, uncompr, uncomprLen)
- const char *fname; /* compressed file name */
- Byte *uncompr;
- uLong uncomprLen;
-{
+static void test_gzio(const char *fname, Byte *uncompr, uLong uncomprLen) {
#ifdef NO_GZCOMPRESS
fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");
#else
@@ -197,10 +169,7 @@ void test_gzio(fname, uncompr, uncomprLen)
/* ===========================================================================
* Test deflate() with small buffers
*/
-void test_deflate(compr, comprLen)
- Byte *compr;
- uLong comprLen;
-{
+static void test_deflate(Byte *compr, uLong comprLen) {
z_stream c_stream; /* compression stream */
int err;
uLong len = (uLong)strlen(hello)+1;
@@ -235,10 +204,8 @@ void test_deflate(compr, comprLen)
/* ===========================================================================
* Test inflate() with small buffers
*/
-void test_inflate(compr, comprLen, uncompr, uncomprLen)
- Byte *compr, *uncompr;
- uLong comprLen, uncomprLen;
-{
+static void test_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
+ uLong uncomprLen) {
int err;
z_stream d_stream; /* decompression stream */
@@ -276,10 +243,8 @@ void test_inflate(compr, comprLen, uncompr, uncomprLen)
/* ===========================================================================
* Test deflate() with large buffers and dynamic change of compression level
*/
-void test_large_deflate(compr, comprLen, uncompr, uncomprLen)
- Byte *compr, *uncompr;
- uLong comprLen, uncomprLen;
-{
+static void test_large_deflate(Byte *compr, uLong comprLen, Byte *uncompr,
+ uLong uncomprLen) {
z_stream c_stream; /* compression stream */
int err;
@@ -308,7 +273,7 @@ void test_large_deflate(compr, comprLen, uncompr, uncomprLen)
/* Feed in already compressed data and switch to no compression: */
deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
c_stream.next_in = compr;
- c_stream.avail_in = (uInt)comprLen/2;
+ c_stream.avail_in = (uInt)uncomprLen/2;
err = deflate(&c_stream, Z_NO_FLUSH);
CHECK_ERR(err, "deflate");
@@ -331,10 +296,8 @@ void test_large_deflate(compr, comprLen, uncompr, uncomprLen)
/* ===========================================================================
* Test inflate() with large buffers
*/
-void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
- Byte *compr, *uncompr;
- uLong comprLen, uncomprLen;
-{
+static void test_large_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
+ uLong uncomprLen) {
int err;
z_stream d_stream; /* decompression stream */
@@ -361,8 +324,8 @@ void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
err = inflateEnd(&d_stream);
CHECK_ERR(err, "inflateEnd");
- if (d_stream.total_out != 2*uncomprLen + comprLen/2) {
- fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out);
+ if (d_stream.total_out != 2*uncomprLen + uncomprLen/2) {
+ fprintf(stderr, "bad large inflate: %lu\n", d_stream.total_out);
exit(1);
} else {
printf("large_inflate(): OK\n");
@@ -372,10 +335,7 @@ void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
/* ===========================================================================
* Test deflate() with full flush
*/
-void test_flush(compr, comprLen)
- Byte *compr;
- uLong *comprLen;
-{
+static void test_flush(Byte *compr, uLong *comprLen) {
z_stream c_stream; /* compression stream */
int err;
uInt len = (uInt)strlen(hello)+1;
@@ -410,10 +370,8 @@ void test_flush(compr, comprLen)
/* ===========================================================================
* Test inflateSync()
*/
-void test_sync(compr, comprLen, uncompr, uncomprLen)
- Byte *compr, *uncompr;
- uLong comprLen, uncomprLen;
-{
+static void test_sync(Byte *compr, uLong comprLen, Byte *uncompr,
+ uLong uncomprLen) {
int err;
z_stream d_stream; /* decompression stream */
@@ -432,7 +390,7 @@ void test_sync(compr, comprLen, uncompr, uncomprLen)
d_stream.next_out = uncompr;
d_stream.avail_out = (uInt)uncomprLen;
- inflate(&d_stream, Z_NO_FLUSH);
+ err = inflate(&d_stream, Z_NO_FLUSH);
CHECK_ERR(err, "inflate");
d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */
@@ -440,9 +398,8 @@ void test_sync(compr, comprLen, uncompr, uncomprLen)
CHECK_ERR(err, "inflateSync");
err = inflate(&d_stream, Z_FINISH);
- if (err != Z_DATA_ERROR) {
- fprintf(stderr, "inflate should report DATA_ERROR\n");
- /* Because of incorrect adler32 */
+ if (err != Z_STREAM_END) {
+ fprintf(stderr, "inflate should report Z_STREAM_END\n");
exit(1);
}
err = inflateEnd(&d_stream);
@@ -454,10 +411,7 @@ void test_sync(compr, comprLen, uncompr, uncomprLen)
/* ===========================================================================
* Test deflate() with preset dictionary
*/
-void test_dict_deflate(compr, comprLen)
- Byte *compr;
- uLong comprLen;
-{
+static void test_dict_deflate(Byte *compr, uLong comprLen) {
z_stream c_stream; /* compression stream */
int err;
@@ -491,10 +445,8 @@ void test_dict_deflate(compr, comprLen)
/* ===========================================================================
* Test inflate() with a preset dictionary
*/
-void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
- Byte *compr, *uncompr;
- uLong comprLen, uncomprLen;
-{
+static void test_dict_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
+ uLong uncomprLen) {
int err;
z_stream d_stream; /* decompression stream */
@@ -542,13 +494,10 @@ void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
* Usage: example [output.gz [input.gz]]
*/
-int main(argc, argv)
- int argc;
- char *argv[];
-{
+int main(int argc, char *argv[]) {
Byte *compr, *uncompr;
- uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
- uLong uncomprLen = comprLen;
+ uLong uncomprLen = 20000;
+ uLong comprLen = 3 * uncomprLen;
static const char* myVersion = ZLIB_VERSION;
if (zlibVersion()[0] != myVersion[0]) {
@@ -556,11 +505,12 @@ int main(argc, argv)
exit(1);
} else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {
- fprintf(stderr, "warning: different zlib version\n");
+ fprintf(stderr, "warning: different zlib version linked: %s\n",
+ zlibVersion());
}
printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n",
- ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags());
+ ZLIB_VERSION, (unsigned)ZLIB_VERNUM, zlibCompileFlags());
compr = (Byte*)calloc((uInt)comprLen, 1);
uncompr = (Byte*)calloc((uInt)uncomprLen, 1);
@@ -573,7 +523,8 @@ int main(argc, argv)
}
#ifdef Z_SOLO
- argc = strlen(argv[0]);
+ (void)argc;
+ (void)argv;
#else
test_compress(compr, comprLen, uncompr, uncomprLen);
@@ -589,7 +540,7 @@ int main(argc, argv)
test_flush(compr, &comprLen);
test_sync(compr, comprLen, uncompr, uncomprLen);
- comprLen = uncomprLen;
+ comprLen = 3 * uncomprLen;
test_dict_deflate(compr, comprLen);
test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
diff --git a/zlib/test/infcover.c b/zlib/test/infcover.c
index fe3d9203a..f1ad0f912 100644
--- a/zlib/test/infcover.c
+++ b/zlib/test/infcover.c
@@ -1,5 +1,5 @@
/* infcover.c -- test zlib's inflate routines with full code coverage
- * Copyright (C) 2011 Mark Adler
+ * Copyright (C) 2011, 2016, 2024 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -185,7 +185,7 @@ local void mem_used(z_stream *strm, char *prefix)
{
struct mem_zone *zone = strm->opaque;
- fprintf(stderr, "%s: %lu allocated\n", prefix, zone->total);
+ fprintf(stderr, "%s: %zu allocated\n", prefix, zone->total);
}
/* show the high water allocation in bytes */
@@ -193,7 +193,7 @@ local void mem_high(z_stream *strm, char *prefix)
{
struct mem_zone *zone = strm->opaque;
- fprintf(stderr, "%s: %lu high water mark\n", prefix, zone->highwater);
+ fprintf(stderr, "%s: %zu high water mark\n", prefix, zone->highwater);
}
/* release the memory allocation zone -- if there are any surprises, notify */
@@ -218,7 +218,7 @@ local void mem_done(z_stream *strm, char *prefix)
/* issue alerts about anything unexpected */
if (count || zone->total)
- fprintf(stderr, "** %s: %lu bytes in %d blocks not freed\n",
+ fprintf(stderr, "** %s: %zu bytes in %d blocks not freed\n",
prefix, zone->total, count);
if (zone->notlifo)
fprintf(stderr, "** %s: %d frees not LIFO\n", prefix, zone->notlifo);
@@ -237,14 +237,14 @@ local void mem_done(z_stream *strm, char *prefix)
/* Decode a hexadecimal string, set *len to length, in[] to the bytes. This
decodes liberally, in that hex digits can be adjacent, in which case two in
- a row writes a byte. Or they can delimited by any non-hex character, where
- the delimiters are ignored except when a single hex digit is followed by a
- delimiter in which case that single digit writes a byte. The returned
- data is allocated and must eventually be freed. NULL is returned if out of
- memory. If the length is not needed, then len can be NULL. */
+ a row writes a byte. Or they can be delimited by any non-hex character,
+ where the delimiters are ignored except when a single hex digit is followed
+ by a delimiter, where that single digit writes a byte. The returned data is
+ allocated and must eventually be freed. NULL is returned if out of memory.
+ If the length is not needed, then len can be NULL. */
local unsigned char *h2b(const char *hex, unsigned *len)
{
- unsigned char *in;
+ unsigned char *in, *re;
unsigned next, val;
in = malloc((strlen(hex) + 1) >> 1);
@@ -268,8 +268,8 @@ local unsigned char *h2b(const char *hex, unsigned *len)
} while (*hex++); /* go through the loop with the terminating null */
if (len != NULL)
*len = next;
- in = reallocf(in, next);
- return in;
+ re = realloc(in, next);
+ return re == NULL ? in : re;
}
/* generic inflate() run, where hex is the hexadecimal input data, what is the
@@ -373,7 +373,7 @@ local void cover_support(void)
mem_setup(&strm);
strm.avail_in = 0;
strm.next_in = Z_NULL;
- ret = inflateInit_(&strm, ZLIB_VERSION - 1, (int)sizeof(z_stream));
+ ret = inflateInit_(&strm, "!", (int)sizeof(z_stream));
assert(ret == Z_VERSION_ERROR);
mem_done(&strm, "wrong version");
@@ -444,7 +444,7 @@ local void cover_wrap(void)
}
/* input and output functions for inflateBack() */
-local unsigned pull(void *desc, unsigned char **buf)
+local unsigned pull(void *desc, unsigned char z_const **buf)
{
static unsigned int next = 0;
static unsigned char dat[] = {0x63, 0, 2, 0};
@@ -462,7 +462,8 @@ local unsigned pull(void *desc, unsigned char **buf)
local int push(void *desc, unsigned char *buf, unsigned len)
{
- buf += len;
+ (void)buf;
+ (void)len;
return desc != Z_NULL; /* force error if desc not null */
}
diff --git a/zlib/test/minigzip.c b/zlib/test/minigzip.c
index b3025a489..40da8736f 100644
--- a/zlib/test/minigzip.c
+++ b/zlib/test/minigzip.c
@@ -1,5 +1,5 @@
/* minigzip.c -- simulate gzip using the zlib compression library
- * Copyright (C) 1995-2006, 2010, 2011 Jean-loup Gailly.
+ * Copyright (C) 1995-2026 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -15,6 +15,17 @@
/* @(#) $Id$ */
+#ifndef _POSIX_C_SOURCE
+# define _POSIX_C_SOURCE 200112L
+#endif
+
+#if defined(_WIN32) && !defined(_CRT_SECURE_NO_WARNINGS)
+# define _CRT_SECURE_NO_WARNINGS
+#endif
+#if defined(_WIN32) && !defined(_CRT_NONSTDC_NO_DEPRECATE)
+# define _CRT_NONSTDC_NO_DEPRECATE
+#endif
+
#include "zlib.h"
#include
@@ -40,18 +51,16 @@
# define SET_BINARY_MODE(file)
#endif
-#ifdef _MSC_VER
-# define snprintf _snprintf
-#endif
-
#ifdef VMS
# define unlink delete
# define GZ_SUFFIX "-gz"
#endif
-#ifdef RISCOS
-# define unlink remove
-# define GZ_SUFFIX "-gz"
-# define fileno(file) file->__file
+#if defined(__riscos) && !defined(__TARGET_UNIXLIB__)
+# define GZ_SUFFIX "/gz"
+# ifndef __GNUC__
+# define unlink remove
+# define fileno(file) file->__file
+# endif
#endif
#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
# include /* for fileno */
@@ -59,7 +68,7 @@
#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE)
#ifndef WIN32 /* unlink already in stdio.h for WIN32 */
- extern int unlink OF((const char *));
+ extern int unlink(const char *);
#endif
#endif
@@ -109,7 +118,7 @@ static char *strwinerror (error)
LocalFree(msgbuf);
}
else {
- sprintf(buf, "unknown win32 error (%ld)", error);
+ sprintf(buf, "unknown win32 error (%lu)", error);
}
SetLastError(lasterr);
@@ -142,6 +151,25 @@ static void pwinerror (s)
# define local
#endif
+/* ===========================================================================
+ * Safe string copy. Copy up to len bytes from src to dst, if src terminates
+ * with a null by then. If not, copy len-1 bytes from src, terminating it with
+ * a null in dst[len-1], cutting src short. Return a pointer to the terminating
+ * null. If len is zero, nothing is written to *dst and NULL is returned.
+ */
+static char *string_copy(char *dst, char const *src, z_size_t len) {
+ if (len == 0)
+ return NULL;
+ while (--len) {
+ *dst = *src++;
+ if (*dst == 0)
+ return dst;
+ dst++;
+ }
+ *dst = 0;
+ return dst;
+}
+
#ifdef Z_SOLO
/* for Z_SOLO, create simplified gz* functions using deflate and inflate */
@@ -149,21 +177,13 @@ static void pwinerror (s)
# include /* for unlink() */
#endif
-void *myalloc OF((void *, unsigned, unsigned));
-void myfree OF((void *, void *));
-
-void *myalloc(q, n, m)
- void *q;
- unsigned n, m;
-{
- q = Z_NULL;
+static void *myalloc(void *q, unsigned n, unsigned m) {
+ (void)q;
return calloc(n, m);
}
-void myfree(q, p)
- void *q, *p;
-{
- q = Z_NULL;
+static void myfree(void *q, void *p) {
+ (void)q;
free(p);
}
@@ -175,29 +195,7 @@ typedef struct gzFile_s {
z_stream strm;
} *gzFile;
-gzFile gzopen OF((const char *, const char *));
-gzFile gzdopen OF((int, const char *));
-gzFile gz_open OF((const char *, int, const char *));
-
-gzFile gzopen(path, mode)
-const char *path;
-const char *mode;
-{
- return gz_open(path, -1, mode);
-}
-
-gzFile gzdopen(fd, mode)
-int fd;
-const char *mode;
-{
- return gz_open(NULL, fd, mode);
-}
-
-gzFile gz_open(path, fd, mode)
- const char *path;
- int fd;
- const char *mode;
-{
+static gzFile gz_open(const char *path, int fd, const char *mode) {
gzFile gz;
int ret;
@@ -231,13 +229,15 @@ gzFile gz_open(path, fd, mode)
return gz;
}
-int gzwrite OF((gzFile, const void *, unsigned));
+static gzFile gzopen(const char *path, const char *mode) {
+ return gz_open(path, -1, mode);
+}
-int gzwrite(gz, buf, len)
- gzFile gz;
- const void *buf;
- unsigned len;
-{
+static gzFile gzdopen(int fd, const char *mode) {
+ return gz_open(NULL, fd, mode);
+}
+
+static int gzwrite(gzFile gz, const void *buf, unsigned len) {
z_stream *strm;
unsigned char out[BUFLEN];
@@ -252,16 +252,10 @@ int gzwrite(gz, buf, len)
(void)deflate(strm, Z_NO_FLUSH);
fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);
} while (strm->avail_out == 0);
- return len;
+ return (int)len;
}
-int gzread OF((gzFile, void *, unsigned));
-
-int gzread(gz, buf, len)
- gzFile gz;
- void *buf;
- unsigned len;
-{
+static int gzread(gzFile gz, void *buf, unsigned len) {
int ret;
unsigned got;
unsigned char in[1];
@@ -275,7 +269,7 @@ int gzread(gz, buf, len)
strm->next_out = (void *)buf;
strm->avail_out = len;
do {
- got = fread(in, 1, 1, gz->file);
+ got = (unsigned)fread(in, 1, 1, gz->file);
if (got == 0)
break;
strm->next_in = in;
@@ -289,14 +283,10 @@ int gzread(gz, buf, len)
if (ret == Z_STREAM_END)
inflateReset(strm);
} while (strm->avail_out);
- return len - strm->avail_out;
+ return (int)(len - strm->avail_out);
}
-int gzclose OF((gzFile));
-
-int gzclose(gz)
- gzFile gz;
-{
+static int gzclose(gzFile gz) {
z_stream *strm;
unsigned char out[BUFLEN];
@@ -321,81 +311,29 @@ int gzclose(gz)
return Z_OK;
}
-const char *gzerror OF((gzFile, int *));
-
-const char *gzerror(gz, err)
- gzFile gz;
- int *err;
-{
+static const char *gzerror(gzFile gz, int *err) {
*err = gz->err;
return gz->msg;
}
#endif
-char *prog;
-
-void error OF((const char *msg));
-void gz_compress OF((FILE *in, gzFile out));
-#ifdef USE_MMAP
-int gz_compress_mmap OF((FILE *in, gzFile out));
-#endif
-void gz_uncompress OF((gzFile in, FILE *out));
-void file_compress OF((char *file, char *mode));
-void file_uncompress OF((char *file));
-int main OF((int argc, char *argv[]));
+static char *prog;
/* ===========================================================================
* Display error message and exit
*/
-void error(msg)
- const char *msg;
-{
+static void error(const char *msg) {
fprintf(stderr, "%s: %s\n", prog, msg);
exit(1);
}
-/* ===========================================================================
- * Compress input to output then close both files.
- */
-
-void gz_compress(in, out)
- FILE *in;
- gzFile out;
-{
- local char buf[BUFLEN];
- int len;
- int err;
-
-#ifdef USE_MMAP
- /* Try first compressing with mmap. If mmap fails (minigzip used in a
- * pipe), use the normal fread loop.
- */
- if (gz_compress_mmap(in, out) == Z_OK) return;
-#endif
- for (;;) {
- len = (int)fread(buf, 1, sizeof(buf), in);
- if (ferror(in)) {
- perror("fread");
- exit(1);
- }
- if (len == 0) break;
-
- if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
- }
- fclose(in);
- if (gzclose(out) != Z_OK) error("failed gzclose");
-}
-
#ifdef USE_MMAP /* MMAP version, Miguel Albrecht */
/* Try compressing the input file at once using mmap. Return Z_OK if
- * if success, Z_ERRNO otherwise.
+ * success, Z_ERRNO otherwise.
*/
-int gz_compress_mmap(in, out)
- FILE *in;
- gzFile out;
-{
+static int gz_compress_mmap(FILE *in, gzFile out) {
int len;
int err;
int ifd = fileno(in);
@@ -424,13 +362,39 @@ int gz_compress_mmap(in, out)
}
#endif /* USE_MMAP */
+/* ===========================================================================
+ * Compress input to output then close both files.
+ */
+
+static void gz_compress(FILE *in, gzFile out) {
+ local char buf[BUFLEN];
+ int len;
+ int err;
+
+#ifdef USE_MMAP
+ /* Try first compressing with mmap. If mmap fails (minigzip used in a
+ * pipe), use the normal fread loop.
+ */
+ if (gz_compress_mmap(in, out) == Z_OK) return;
+#endif
+ for (;;) {
+ len = (int)fread(buf, 1, sizeof(buf), in);
+ if (ferror(in)) {
+ perror("fread");
+ exit(1);
+ }
+ if (len == 0) break;
+
+ if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
+ }
+ fclose(in);
+ if (gzclose(out) != Z_OK) error("failed gzclose");
+}
+
/* ===========================================================================
* Uncompress input to output then close both files.
*/
-void gz_uncompress(in, out)
- gzFile in;
- FILE *out;
-{
+static void gz_uncompress(gzFile in, FILE *out) {
local char buf[BUFLEN];
int len;
int err;
@@ -454,11 +418,8 @@ void gz_uncompress(in, out)
* Compress the given file: create a corresponding .gz file and remove the
* original.
*/
-void file_compress(file, mode)
- char *file;
- char *mode;
-{
- local char outfile[MAX_NAME_LEN];
+static void file_compress(char *file, char *mode) {
+ local char outfile[MAX_NAME_LEN+1], *end;
FILE *in;
gzFile out;
@@ -467,12 +428,8 @@ void file_compress(file, mode)
exit(1);
}
-#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
- snprintf(outfile, sizeof(outfile), "%s%s", file, GZ_SUFFIX);
-#else
- strcpy(outfile, file);
- strcat(outfile, GZ_SUFFIX);
-#endif
+ end = string_copy(outfile, file, sizeof(outfile));
+ string_copy(end, GZ_SUFFIX, sizeof(outfile) - (z_size_t)(end - outfile));
in = fopen(file, "rb");
if (in == NULL) {
@@ -481,6 +438,7 @@ void file_compress(file, mode)
}
out = gzopen(outfile, mode);
if (out == NULL) {
+ fclose(in);
fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
exit(1);
}
@@ -493,25 +451,19 @@ void file_compress(file, mode)
/* ===========================================================================
* Uncompress the given file and remove the original.
*/
-void file_uncompress(file)
- char *file;
-{
- local char buf[MAX_NAME_LEN];
+static void file_uncompress(char *file) {
+ local char buf[MAX_NAME_LEN+1];
char *infile, *outfile;
FILE *out;
gzFile in;
- size_t len = strlen(file);
+ z_size_t len = strlen(file);
if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) {
fprintf(stderr, "%s: filename too long\n", prog);
exit(1);
}
-#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
- snprintf(buf, sizeof(buf), "%s", file);
-#else
- strcpy(buf, file);
-#endif
+ string_copy(buf, file, sizeof(buf));
if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
infile = file;
@@ -520,11 +472,7 @@ void file_uncompress(file)
} else {
outfile = file;
infile = buf;
-#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
- snprintf(buf + len, sizeof(buf) - len, "%s", GZ_SUFFIX);
-#else
- strcat(infile, GZ_SUFFIX);
-#endif
+ string_copy(buf + len, GZ_SUFFIX, sizeof(buf) - len);
}
in = gzopen(infile, "rb");
if (in == NULL) {
@@ -533,6 +481,7 @@ void file_uncompress(file)
}
out = fopen(outfile, "wb");
if (out == NULL) {
+ gzclose(in);
perror(file);
exit(1);
}
@@ -553,21 +502,13 @@ void file_uncompress(file)
* -1 to -9 : compression level
*/
-int main(argc, argv)
- int argc;
- char *argv[];
-{
+int main(int argc, char *argv[]) {
int copyout = 0;
int uncompr = 0;
gzFile file;
- char *bname, outmode[20];
-
-#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
- snprintf(outmode, sizeof(outmode), "%s", "wb6 ");
-#else
- strcpy(outmode, "wb6 ");
-#endif
+ char *bname, outmode[5];
+ string_copy(outmode, "wb6 ", sizeof(outmode));
prog = argv[0];
bname = strrchr(argv[0], '/');
if (bname)
diff --git a/zlib/treebuild.xml b/zlib/treebuild.xml
index 38d29d75e..cd7d7a587 100644
--- a/zlib/treebuild.xml
+++ b/zlib/treebuild.xml
@@ -1,6 +1,6 @@
-
-
+
+
zip compression library
@@ -101,7 +101,7 @@