/CVE-2003-0107
.DS_Store
+*_fuzzer
*.obj
*.exe
*.pdb
add_definitions(-DWITH_GZFILEOP)
endif (WITH_GZFILEOP)
+option(WITH_SANITIZERS "Build with address sanitizer and all supported sanitizers other than memory sanitizer" OFF)
+option(WITH_MSAN "Build with memory sanitizer" OFF)
+option(WITH_FUZZERS "Build test/fuzz" OFF)
option(WITH_OPTIM "Build with optimisation" ON)
option(WITH_NEW_STRATEGIES "Use new strategies" ON)
option(WITH_NATIVE_INSTRUCTIONS
add_feature_info(ZLIB_COMPAT ZLIB_COMPAT "Provide a zlib-compatible API")
add_feature_info(WITH_GZFILEOP WITH_GZFILEOP "Compile with support for gzFile-related functions")
add_feature_info(WITH_OPTIM WITH_OPTIM "Build with optimisation")
+add_feature_info(WITH_SANITIZERS WITH_SANITIZERS "Build with address sanitizer and all supported sanitizers other than memory sanitizer")
+add_feature_info(WITH_MSAN WITH_MSAN "Build with memory sanitizer")
+add_feature_info(WITH_FUZZERS WITH_FUZZERS "Build test/fuzz")
add_feature_info(WITH_NEW_STRATEGIES WITH_NEW_STRATEGIES "Use new strategies")
if("${ARCH}" MATCHES "arm" OR "${ARCH}" MATCHES "aarch64")
add_feature_info(WITH_ACLE WITH_ACLE "Build with ACLE CRC")
check_include_file(unistd.h Z_HAVE_UNISTD_H)
check_include_file(stdarg.h Z_HAVE_STDARG_H)
+if(WITH_SANITIZERS AND WITH_MSAN)
+ message(FATAL_ERROR "Memory sanitizer is incompatible with address sanitizer")
+endif()
+
+if(WITH_MSAN)
+ set(CMAKE_REQUIRED_FLAGS "-fsanitize=memory")
+ check_c_source_compiles("int main() { return 0; }" HAS_MSAN FAIL_REGEX "not supported")
+ if(${HAS_MSAN})
+ set(SANITIZERS_FLAGS "-fsanitize=memory")
+ message(STATUS "Adding memory sanitizer flag: ${SANITIZERS_FLAGS}")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZERS_FLAGS}")
+ endif()
+endif()
+
+if(WITH_SANITIZERS)
+ set(_sanitize_flags
+ bool
+ address
+ array-bounds
+ float-divide-by-zero
+ function
+ integer-divide-by-zero
+ return
+ shift
+ signed-integer-overflow
+ undefined
+ unsigned-integer-overflow
+ vla-bound
+ vptr
+ )
+ set(SANITIZERS_FLAGS "")
+ foreach(_flag ${_sanitize_flags})
+ set(CMAKE_REQUIRED_FLAGS "-fsanitize=${_flag}")
+ check_c_source_compiles("int main() { return 0; }"
+ HAS_SANITIZER_${_flag} FAIL_REGEX "not supported")
+ if(${HAS_SANITIZER_${_flag}})
+ if("${SANITIZERS_FLAGS}" STREQUAL "")
+ set(SANITIZERS_FLAGS "-fsanitize=${_flag}")
+ else()
+ set(SANITIZERS_FLAGS "${SANITIZERS_FLAGS},${_flag}")
+ endif()
+ endif()
+ set(CMAKE_REQUIRED_FLAGS)
+ endforeach()
+ message(STATUS "Adding sanitizers flags: ${SANITIZERS_FLAGS}")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZERS_FLAGS}")
+endif()
+
#
# Check if we can hide zlib internal symbols that are linked between separate source files using hidden
#
target_link_libraries(minigzip64 zlib)
set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
endif()
+
+ if(WITH_FUZZERS)
+ add_executable(checksum_fuzzer test/fuzz/checksum_fuzzer.c test/fuzz/standalone_fuzz_target_runner.c)
+ add_executable(compress_fuzzer test/fuzz/compress_fuzzer.c test/fuzz/standalone_fuzz_target_runner.c)
+ add_executable(example_small_fuzzer test/fuzz/example_small_fuzzer.c test/fuzz/standalone_fuzz_target_runner.c)
+ add_executable(example_large_fuzzer test/fuzz/example_large_fuzzer.c test/fuzz/standalone_fuzz_target_runner.c)
+ add_executable(example_flush_fuzzer test/fuzz/example_flush_fuzzer.c test/fuzz/standalone_fuzz_target_runner.c)
+ add_executable(example_dict_fuzzer test/fuzz/example_dict_fuzzer.c test/fuzz/standalone_fuzz_target_runner.c)
+ add_executable(minigzip_fuzzer test/fuzz/minigzip_fuzzer.c test/fuzz/standalone_fuzz_target_runner.c)
+
+ target_link_libraries(checksum_fuzzer zlib)
+ target_link_libraries(compress_fuzzer zlib)
+ target_link_libraries(example_small_fuzzer zlib)
+ target_link_libraries(example_large_fuzzer zlib)
+ target_link_libraries(example_flush_fuzzer zlib)
+ target_link_libraries(example_dict_fuzzer zlib)
+ target_link_libraries(minigzip_fuzzer zlib)
+
+ file(GLOB ALL_SRC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*")
+ add_test(checksum_fuzzer checksum_fuzzer${CMAKE_EXECUTABLE_SUFFIX} ${ALL_SRC_FILES})
+ add_test(compress_fuzzer compress_fuzzer${CMAKE_EXECUTABLE_SUFFIX} ${ALL_SRC_FILES})
+ add_test(example_small_fuzzer example_small_fuzzer${CMAKE_EXECUTABLE_SUFFIX} ${ALL_SRC_FILES})
+ add_test(example_large_fuzzer example_large_fuzzer${CMAKE_EXECUTABLE_SUFFIX} ${ALL_SRC_FILES})
+ add_test(example_flush_fuzzer example_flush_fuzzer${CMAKE_EXECUTABLE_SUFFIX} ${ALL_SRC_FILES})
+ add_test(example_dict_fuzzer example_dict_fuzzer${CMAKE_EXECUTABLE_SUFFIX} ${ALL_SRC_FILES})
+ add_test(minigzip_fuzzer minigzip_fuzzer${CMAKE_EXECUTABLE_SUFFIX} ${ALL_SRC_FILES})
+ endif()
endif()
FEATURE_SUMMARY(WHAT ALL INCLUDE_QUIET_PACKAGES)
#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
# -Wstrict-prototypes -Wmissing-prototypes
+WITH_SANITIZERS=
+WITH_MSAN=
+WITH_FUZZERS=
+SANITIZERS_CFLAGS=
+MSAN_CFLAGS=
+
SFLAGS=-O
LDFLAGS=-L.
LIBNAME1=libz-ng
all: static shared
-static: example$(EXE) minigzip$(EXE)
+static: example$(EXE) minigzip$(EXE) fuzzers
shared: examplesh$(EXE) minigzipsh$(EXE)
test: all
$(MAKE) -C test
+# By default, use our own standalone_fuzz_target_runner.
+# This runner does no fuzzing, but simply executes the inputs
+# provided via parameters.
+# Run e.g. "make all LIB_FUZZING_ENGINE=/path/to/libFuzzer.a"
+# to link the fuzzer(s) against a real fuzzing engine.
+ifneq (,$(LIB_FUZZING_ENGINE))
+ # OSS-Fuzz will define its own value for LIB_FUZZING_ENGINE.
+ WITH_FUZZERS=1
+else
+ LIB_FUZZING_ENGINE = standalone_fuzz_target_runner.o
+ ifeq (1,$(WITH_SANITIZERS))
+ CFLAGS := $(CFLAGS) $(SANITIZERS_CFLAGS)
+ LDFLAGS := $(LDFLAGS) $(SANITIZERS_CFLAGS)
+ else
+ ifeq (1,$(WITH_MSAN))
+ CFLAGS := $(CFLAGS) $(MSAN_CFLAGS)
+ LDFLAGS := $(LDFLAGS) $(MSAN_CFLAGS)
+ endif
+ endif
+endif
+
+ifeq (1,$(WITH_FUZZERS))
+fuzzers: checksum_fuzzer$(EXE) compress_fuzzer$(EXE) example_small_fuzzer$(EXE) example_large_fuzzer$(EXE) example_flush_fuzzer$(EXE) example_dict_fuzzer$(EXE) minigzip_fuzzer$(EXE)
+else
+fuzzers:
+endif
+
+# The standalone fuzz target runner.
+standalone_fuzz_target_runner.o: $(SRCDIR)/test/fuzz/standalone_fuzz_target_runner.c
+ $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
+checksum_fuzzer.o: $(SRCDIR)/test/fuzz/checksum_fuzzer.c
+ $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
+compress_fuzzer.o: $(SRCDIR)/test/fuzz/compress_fuzzer.c
+ $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
+example_small_fuzzer.o: $(SRCDIR)/test/fuzz/example_small_fuzzer.c
+ $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
+example_large_fuzzer.o: $(SRCDIR)/test/fuzz/example_large_fuzzer.c
+ $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
+example_flush_fuzzer.o: $(SRCDIR)/test/fuzz/example_flush_fuzzer.c
+ $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
+example_dict_fuzzer.o: $(SRCDIR)/test/fuzz/example_dict_fuzzer.c
+ $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
+minigzip_fuzzer.o: $(SRCDIR)/test/fuzz/minigzip_fuzzer.c
+ $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
+checksum_fuzzer$(EXE): checksum_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB)
+ $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) checksum_fuzzer.o $(STATICLIB) -lpthread
+compress_fuzzer$(EXE): compress_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB)
+ $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) compress_fuzzer.o $(STATICLIB) -lpthread
+example_small_fuzzer$(EXE): example_small_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB)
+ $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) example_small_fuzzer.o $(STATICLIB) -lpthread
+example_large_fuzzer$(EXE): example_large_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB)
+ $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) example_large_fuzzer.o $(STATICLIB) -lpthread
+example_flush_fuzzer$(EXE): example_flush_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB)
+ $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) example_flush_fuzzer.o $(STATICLIB) -lpthread
+example_dict_fuzzer$(EXE): example_dict_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB)
+ $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) example_dict_fuzzer.o $(STATICLIB) -lpthread
+minigzip_fuzzer$(EXE): minigzip_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB)
+ $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) minigzip_fuzzer.o $(STATICLIB) -lpthread
+
infcover.o: $(SRCDIR)/test/infcover.c $(SRCDIR)/zlib$(SUFFIX).h zconf$(SUFFIX).h
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/test/infcover.c
rm -f *.o *.lo *~ \
example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \
example64$(EXE) minigzip64$(EXE) \
+ checksum_fuzzer$(EXE) compress_fuzzer$(EXE) example_small_fuzzer$(EXE) example_large_fuzzer$(EXE) \
+ example_flush_fuzzer$(EXE) example_dict_fuzzer$(EXE) minigzip_fuzzer$(EXE) \
infcover \
$(STATICLIB) $(IMPORTLIB) $(SHAREDLIB) $(SHAREDLIBV) $(SHAREDLIBM) \
foo.gz so_locations \
build64=0
buildacle=0
buildneon=0
+with_sanitizers=0
+with_msan=0
+with_fuzzers=0
floatabi=
native=0
sse2flag="-msse2"
echo ' [--without-optimizations] Compiles without support for optional instruction sets' | tee -a configure.log
echo ' [--without-new-strategies] Compiles without using new additional deflate strategies' | tee -a configure.log
echo ' [--acle] [--neon] Compiles with additional instruction set enabled' | tee -a configure.log
+ echo ' [--with-sanitizers] Build with address sanitizer and all supported sanitizers other than memory sanitizer (disabled by default)' | tee -a configure.log
+ echo ' [--with-msan] Build with memory sanitizer (disabled by default)' | tee -a configure.log
+ echo ' [--with-fuzzers] Build test/fuzz (disabled by default)' | tee -a configure.log
exit 0 ;;
-p*=* | --prefix=*) prefix=`echo $1 | sed 's/.*=//'`; shift ;;
-e*=* | --eprefix=*) exec_prefix=`echo $1 | sed 's/.*=//'`; shift ;;
-oldstrat | --without-new-strategies) without_new_strategies=1; shift;;
-w* | --warn) warn=1; shift ;;
-d* | --debug) debug=1; shift ;;
+ --with-sanitizers) with_sanitizers=1; shift ;;
+ --with-msan) with_msan=1; shift ;;
+ --with-fuzzers) with_fuzzers=1; shift ;;
*)
echo "unknown option: $1" | tee -a configure.log
echo "$0 --help for help" | tee -a configure.log
CC="$cc"
CFLAGS="${CFLAGS} -std=c99"
# Re-check arch if gcc is a cross-compiler
- GCC_ARCH=`$CC -dumpmachine | sed 's/-.*//g'`
+ GCC_ARCH=`$CC $CFLAGS -dumpmachine | sed 's/-.*//g'`
case $GCC_ARCH in
i386 | i486 | i586 | i686)
# Honor user choice if gcc is multilib and 64-bit is requested
echo >> configure.log
+if test $with_sanitizers -eq 1; then
+ if test $with_msan -eq 1; then
+ echo "Error: --with-sanitizers and --with-msan cannot be used together"
+ exit 1
+ fi
+ echo -n "Checking for sanitizers ASan/UBSan... " | tee -a configure.log
+ sanitizers=""
+ for san in bool address array-bounds float-divide-by-zero function integer-divide-by-zero return shift signed-integer-overflow undefined unsigned-integer-overflow vla-bound vptr; do
+ if try $CC -c $CFLAGS $test.c -fsanitize=$san ; then
+ if test -n "$sanitizers"; then
+ sanitizers="$sanitizers,$san"
+ else
+ sanitizers="$san"
+ fi
+ fi
+ done
+
+ SANITIZERS_CFLAGS=""
+ if test -n "$sanitizers"; then
+ echo "-fsanitize=$sanitizers" | tee -a configure.log
+ SANITIZERS_CFLAGS="-fsanitize=$sanitizers"
+ else
+ echo No | tee -a configure.log
+ with_sanitizers=0
+ fi
+
+ echo >> configure.log
+fi
+
+if test $with_msan -eq 1; then
+ echo -n "Checking for MSan... " | tee -a configure.log
+ if try $CC -c $CFLAGS $test.c -fsanitize=memory ; then
+ echo "-fsanitize=memory" | tee -a configure.log
+ MSAN_CFLAGS="-fsanitize=memory"
+ else
+ echo No | tee -a configure.log
+ MSAN_CFLAGS=""
+ with_msan=0
+ fi
+
+ echo >> configure.log
+fi
+
# see if shared library build supported
cat > $test.c <<EOF
extern int getchar();
sed < $SRCDIR/Makefile.in "
/^CC *=/s#=.*#=$CC#
/^CFLAGS *=/s#=.*#=$CFLAGS#
+/^WITH_SANITIZERS *=/s#=.*#=$with_sanitizers#
+/^WITH_MSAN *=/s#=.*#=$with_msan#
+/^WITH_FUZZERS *=/s#=.*#=$with_fuzzers#
+/^SANITIZERS_CFLAGS *=/s#=.*#=$SANITIZERS_CFLAGS#
+/^MSAN_CFLAGS *=/s#=.*#=$MSAN_CFLAGS#
/^SFLAGS *=/s#=.*#=$SFLAGS#
/^LDFLAGS *=/s#=.*#=$LDFLAGS#
/^LDSHARED *=/s#=.*#=$LDSHARED#
/^SRCTOP *=/s#=.*#=$SRCDIR#
/^COMPATTESTS *=/s#=.*#=$COMPATTESTS#
/^QEMU_RUN *=/s#=.*#=$QEMU_RUN#
+/^WITH_FUZZERS *=/s#=.*#=$with_fuzzers#
" > test/Makefile
# create zlib.pc with the configure results
SRCTOP=
INCLUDES=
TEST_LDFLAGS=-L.. ../libz.a
+WITH_FUZZERS=
COMPATTESTS =
QEMU_RUN=
QEMU_VER:=$(shell command -v $(QEMU_RUN) --version 2> /dev/null)
-all: oldtests cvetests $(COMPATTESTS)
+all: oldtests cvetests $(COMPATTESTS) fuzzer
oldtests: #set by ../configure
check_cross_dep:
endif
endif
+ALL_SRC_FILES := $(wildcard ../*)
+
+# Only check the fuzzer when it is a stand-alone executable.
+ifneq (,$(LIB_FUZZING_ENGINE))
+fuzzer:
+else
+ ifeq (0,$(WITH_FUZZERS))
+fuzzer:
+ else
+fuzzer:
+ @${QEMU_RUN} ../checksum_fuzzer$(EXE) $(ALL_SRC_FILES) ; \
+ ${QEMU_RUN} ../compress_fuzzer$(EXE) $(ALL_SRC_FILES) ; \
+ ${QEMU_RUN} ../example_small_fuzzer$(EXE) $(ALL_SRC_FILES) ; \
+ ${QEMU_RUN} ../example_large_fuzzer$(EXE) $(ALL_SRC_FILES) ; \
+ ${QEMU_RUN} ../example_flush_fuzzer$(EXE) $(ALL_SRC_FILES) ; \
+ ${QEMU_RUN} ../example_dict_fuzzer$(EXE) $(ALL_SRC_FILES); \
+ ${QEMU_RUN} ../minigzip_fuzzer$(EXE) $(ALL_SRC_FILES)
+ endif
+endif
+
teststatic: check_cross_dep
@TMPST=tmpst_$$; \
if echo hello world | ${QEMU_RUN} ../minigzip$(EXE) | ${QEMU_RUN} ../minigzip$(EXE) -d && ${QEMU_RUN} ../example$(EXE) $$TMPST ; then \
--- /dev/null
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "zbuild.h"
+#ifdef ZLIB_COMPAT
+# include "zlib.h"
+#else
+# include "zlib-ng.h"
+#endif
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataLen) {
+ uint32_t crc1 = PREFIX(crc32)(0L, NULL, 0);
+ uint32_t crc2 = PREFIX(crc32)(0L, NULL, 0);
+ uint32_t adler1 = PREFIX(adler32)(0L, NULL, 0);
+ uint32_t adler2 = PREFIX(adler32)(0L, NULL, 0);;
+ /* Checksum with a buffer of size equal to the first byte in the input. */
+ uint32_t buffSize = data[0];
+ uint32_t offset = 0;
+
+ /* Discard inputs larger than 1Mb. */
+ static size_t kMaxSize = 1024 * 1024;
+ if (dataLen < 1 || dataLen > kMaxSize)
+ return 0;
+
+ /* Make sure the buffer has at least a byte. */
+ if (buffSize == 0)
+ ++buffSize;
+
+ /* CRC32 */
+ for (offset = 0; offset + buffSize <= dataLen; offset += buffSize)
+ crc1 = PREFIX(crc32_z)(crc1, data + offset, buffSize);
+ crc1 = PREFIX(crc32_z)(crc1, data + offset, dataLen % buffSize);
+
+ crc2 = PREFIX(crc32_z)(crc2, data, dataLen);
+
+ assert(crc1 == crc2);
+ assert(PREFIX(crc32_combine)(crc1, crc2, dataLen) ==
+ PREFIX(crc32_combine)(crc1, crc1, dataLen));
+
+ /* Adler32 */
+ for (offset = 0; offset + buffSize <= dataLen; offset += buffSize)
+ adler1 = PREFIX(adler32_z)(adler1, data + offset, buffSize);
+ adler1 = PREFIX(adler32_z)(adler1, data + offset, dataLen % buffSize);
+
+ adler2 = PREFIX(adler32_z)(adler2, data, dataLen);
+
+ assert(adler1 == adler2);
+ assert(PREFIX(adler32_combine)(adler1, adler2, dataLen) ==
+ PREFIX(adler32_combine)(adler1, adler1, dataLen));
+
+ /* This function must return 0. */
+ return 0;
+}
--- /dev/null
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "zbuild.h"
+#ifdef ZLIB_COMPAT
+# include "zlib.h"
+#else
+# include "zlib-ng.h"
+#endif
+
+static const uint8_t *data;
+static size_t dataLen;
+
+static void check_compress_level(uint8_t *compr, size_t comprLen,
+ uint8_t *uncompr, size_t uncomprLen,
+ int level) {
+ PREFIX(compress2)(compr, &comprLen, data, dataLen, level);
+ PREFIX(uncompress)(uncompr, &uncomprLen, compr, comprLen);
+
+ /* Make sure compress + uncompress gives back the input data. */
+ assert(dataLen == uncomprLen);
+ assert(0 == memcmp(data, uncompr, dataLen));
+}
+
+#define put_byte(s, i, c) {s[i] = (unsigned char)(c);}
+
+static void write_zlib_header(uint8_t *s) {
+ unsigned level_flags = 0; /* compression level (0..3) */
+ unsigned w_bits = 8; /* window size log2(w_size) (8..16) */
+ unsigned int header = (Z_DEFLATED + ((w_bits-8)<<4)) << 8;
+ header |= (level_flags << 6);
+
+ header += 31 - (header % 31);
+
+ /* s is guaranteed to be longer than 2 bytes. */
+ put_byte(s, 0, (unsigned char)(header >> 8));
+ put_byte(s, 1, (unsigned char)(header & 0xff));
+}
+
+static void check_decompress(uint8_t *compr, size_t comprLen) {
+ /* We need to write a valid zlib header of size two bytes. Copy the input data
+ in a larger buffer. Do not modify the input data to avoid libFuzzer error:
+ fuzz target overwrites its const input. */
+ size_t copyLen = dataLen + 2;
+ uint8_t *copy = (uint8_t *)malloc(copyLen);
+ memcpy(copy + 2, data, dataLen);
+ write_zlib_header(copy);
+
+ PREFIX(uncompress)(compr, &comprLen, copy, copyLen);
+ free(copy);
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *d, size_t size) {
+ /* compressBound does not provide enough space for low compression levels. */
+ size_t comprLen = 100 + 2 * PREFIX(compressBound)(size);
+ size_t uncomprLen = size;
+ uint8_t *compr, *uncompr;
+
+ /* Discard inputs larger than 1Mb. */
+ static size_t kMaxSize = 1024 * 1024;
+
+ if (size < 1 || size > kMaxSize)
+ return 0;
+
+ data = d;
+ dataLen = size;
+ compr = (uint8_t *)calloc(1, comprLen);
+ uncompr = (uint8_t *)calloc(1, uncomprLen);
+
+ check_compress_level(compr, comprLen, uncompr, uncomprLen, 1);
+ check_compress_level(compr, comprLen, uncompr, uncomprLen, 3);
+ check_compress_level(compr, comprLen, uncompr, uncomprLen, 6);
+ check_compress_level(compr, comprLen, uncompr, uncomprLen, 7);
+
+ check_decompress(compr, comprLen);
+
+ free(compr);
+ free(uncompr);
+
+ /* This function must return 0. */
+ return 0;
+}
--- /dev/null
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "zbuild.h"
+#ifdef ZLIB_COMPAT
+# include "zlib.h"
+#else
+# include "zlib-ng.h"
+#endif
+
+#define CHECK_ERR(err, msg) { \
+ if (err != Z_OK) { \
+ fprintf(stderr, "%s error: %d\n", msg, err); \
+ exit(1); \
+ } \
+}
+
+static const uint8_t *data;
+static size_t dataLen;
+static alloc_func zalloc = NULL;
+static free_func zfree = NULL;
+static size_t dictionaryLen = 0;
+static unsigned long dictId; /* Adler32 value of the dictionary */
+
+/* ===========================================================================
+ * Test deflate() with preset dictionary
+ */
+void test_dict_deflate(unsigned char **compr, size_t *comprLen)
+{
+ PREFIX3(stream) c_stream; /* compression stream */
+ int err;
+ int level = data[0] % 11 - 1; /* [-1..9]
+ compression levels
+ #define Z_NO_COMPRESSION 0
+ #define Z_BEST_SPEED 1
+ #define Z_BEST_COMPRESSION 9
+ #define Z_DEFAULT_COMPRESSION (-1) */
+
+ int method = Z_DEFLATED; /* The deflate compression method (the only one
+ supported in this version) */
+ int windowBits = 8 + data[0] % 8; /* The windowBits parameter is the base
+ two logarithm of the window size (the size of the history buffer). It
+ should be in the range 8..15 for this version of the library. */
+ int memLevel = 1 + data[0] % 9; /* memLevel=1 uses minimum memory but is
+ slow and reduces compression ratio; memLevel=9 uses maximum memory for
+ optimal speed. */
+ int strategy = data[0] % 5; /* [0..4]
+ #define Z_FILTERED 1
+ #define Z_HUFFMAN_ONLY 2
+ #define Z_RLE 3
+ #define Z_FIXED 4
+ #define Z_DEFAULT_STRATEGY 0 */
+
+ /* deflate would fail for no-compression or for speed levels. */
+ if (level == 0 || level == 1)
+ level = -1;
+
+ c_stream.zalloc = zalloc;
+ c_stream.zfree = zfree;
+ c_stream.opaque = (void *)0;
+
+ err = PREFIX(deflateInit2)(&c_stream, level, method, windowBits, memLevel,
+ strategy);
+ CHECK_ERR(err, "deflateInit");
+
+ err = PREFIX(deflateSetDictionary)(
+ &c_stream, (const unsigned char *)data, dictionaryLen);
+ CHECK_ERR(err, "deflateSetDictionary");
+
+ /* deflateBound does not provide enough space for low compression levels. */
+ *comprLen = 100 + 2 * PREFIX(deflateBound)(&c_stream, dataLen);
+ *compr = (uint8_t *)calloc(1, *comprLen);
+
+ dictId = c_stream.adler;
+ c_stream.next_out = *compr;
+ c_stream.avail_out = (unsigned int)(*comprLen);
+
+ c_stream.next_in = data;
+ c_stream.avail_in = dataLen;
+
+ err = PREFIX(deflate)(&c_stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ fprintf(stderr, "deflate dict should report Z_STREAM_END\n");
+ exit(1);
+ }
+ err = PREFIX(deflateEnd)(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with a preset dictionary
+ */
+void test_dict_inflate(unsigned char *compr, size_t comprLen) {
+ int err;
+ PREFIX3(stream) d_stream; /* decompression stream */
+ unsigned char *uncompr;
+
+ d_stream.zalloc = zalloc;
+ d_stream.zfree = zfree;
+ d_stream.opaque = (void *)0;
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = (unsigned int)comprLen;
+
+ err = PREFIX(inflateInit)(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ uncompr = (uint8_t *)calloc(1, dataLen);
+ d_stream.next_out = uncompr;
+ d_stream.avail_out = (unsigned int)dataLen;
+
+ for (;;) {
+ err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH);
+ if (err == Z_STREAM_END)
+ break;
+ if (err == Z_NEED_DICT) {
+ if (d_stream.adler != dictId) {
+ fprintf(stderr, "unexpected dictionary");
+ exit(1);
+ }
+ err = PREFIX(inflateSetDictionary)(
+ &d_stream, (const unsigned char *)data, dictionaryLen);
+ }
+ CHECK_ERR(err, "inflate with dict");
+ }
+
+ err = PREFIX(inflateEnd)(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ if (memcmp(uncompr, data, dataLen)) {
+ fprintf(stderr, "bad inflate with dict\n");
+ exit(1);
+ }
+
+ free(uncompr);
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *d, size_t size) {
+ size_t comprLen = 0;
+ uint8_t *compr;
+
+ /* Discard inputs larger than 100Kb. */
+ static size_t kMaxSize = 100 * 1024;
+
+ if (size < 1 || size > kMaxSize)
+ return 0;
+
+ data = d;
+ dataLen = size;
+
+ /* Set up the contents of the dictionary. The size of the dictionary is
+ intentionally selected to be of unusual size. To help cover more corner
+ cases, the size of the dictionary is read from the input data. */
+ dictionaryLen = data[0];
+ if (dictionaryLen > dataLen)
+ dictionaryLen = dataLen;
+
+ test_dict_deflate(&compr, &comprLen);
+ test_dict_inflate(compr, comprLen);
+
+ free(compr);
+
+ /* This function must return 0. */
+ return 0;
+}
--- /dev/null
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "zbuild.h"
+#ifdef ZLIB_COMPAT
+# include "zlib.h"
+#else
+# include "zlib-ng.h"
+#endif
+
+#define CHECK_ERR(err, msg) { \
+ if (err != Z_OK) { \
+ fprintf(stderr, "%s error: %d\n", msg, err); \
+ exit(1); \
+ } \
+}
+
+static const uint8_t *data;
+static size_t dataLen;
+static alloc_func zalloc = NULL;
+static free_func zfree = NULL;
+
+/* ===========================================================================
+ * Test deflate() with full flush
+ */
+void test_flush(unsigned char *compr, z_size_t *comprLen) {
+ PREFIX3(stream) c_stream; /* compression stream */
+ int err;
+ unsigned int len = dataLen;
+
+ c_stream.zalloc = zalloc;
+ c_stream.zfree = zfree;
+ c_stream.opaque = (void *)0;
+
+ err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION);
+ CHECK_ERR(err, "deflateInit");
+
+ c_stream.next_in = (const unsigned char *)data;
+ c_stream.next_out = compr;
+ c_stream.avail_in = 3;
+ c_stream.avail_out = (unsigned int)*comprLen;
+ err = PREFIX(deflate)(&c_stream, Z_FULL_FLUSH);
+ CHECK_ERR(err, "deflate flush 1");
+
+ compr[3]++; /* force an error in first compressed block */
+ c_stream.avail_in = len - 3;
+
+ err = PREFIX(deflate)(&c_stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ CHECK_ERR(err, "deflate flush 2");
+ }
+ err = PREFIX(deflateEnd)(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+
+ *comprLen = (z_size_t)c_stream.total_out;
+}
+
+/* ===========================================================================
+ * Test inflateSync()
+ */
+void test_sync(unsigned char *compr, size_t comprLen, unsigned char *uncompr,
+ size_t uncomprLen) {
+ int err;
+ PREFIX3(stream) d_stream; /* decompression stream */
+
+ d_stream.zalloc = zalloc;
+ d_stream.zfree = zfree;
+ d_stream.opaque = (void *)0;
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = 2; /* just read the zlib header */
+
+ err = PREFIX(inflateInit)(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ d_stream.next_out = uncompr;
+ d_stream.avail_out = (unsigned int)uncomprLen;
+
+ err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "inflate");
+
+ d_stream.avail_in = (unsigned int)comprLen - 2; /* read all compressed data */
+ err = PREFIX(inflateSync)(&d_stream); /* but skip the damaged part */
+ CHECK_ERR(err, "inflateSync");
+
+ err = PREFIX(inflate)(&d_stream, Z_FINISH);
+ if (err != Z_DATA_ERROR) {
+ fprintf(stderr, "inflate should report DATA_ERROR\n");
+ /* Because of incorrect adler32 */
+ exit(1);
+ }
+ err = PREFIX(inflateEnd)(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *d, size_t size) {
+ size_t comprLen = 100 + 2 * PREFIX(compressBound)(size);
+ size_t uncomprLen = size;
+ uint8_t *compr, *uncompr;
+
+ /* Discard inputs larger than 1Mb. */
+ static size_t kMaxSize = 1024 * 1024;
+
+ // This test requires at least 3 bytes of input data.
+ if (size <= 3 || size > kMaxSize)
+ return 0;
+
+ data = d;
+ dataLen = size;
+ compr = (uint8_t *)calloc(1, comprLen);
+ uncompr = (uint8_t *)calloc(1, uncomprLen);
+
+ test_flush(compr, &comprLen);
+ test_sync(compr, comprLen, uncompr, uncomprLen);
+
+ free(compr);
+ free(uncompr);
+
+ /* This function must return 0. */
+ return 0;
+}
--- /dev/null
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "zbuild.h"
+#ifdef ZLIB_COMPAT
+# include "zlib.h"
+#else
+# include "zlib-ng.h"
+#endif
+
+#define CHECK_ERR(err, msg) { \
+ if (err != Z_OK) { \
+ fprintf(stderr, "%s error: %d\n", msg, err); \
+ exit(1); \
+ } \
+}
+
+static const uint8_t *data;
+static size_t dataLen;
+static alloc_func zalloc = NULL;
+static free_func zfree = NULL;
+static unsigned int diff;
+
+/* ===========================================================================
+ * Test deflate() with large buffers and dynamic change of compression level
+ */
+void test_large_deflate(unsigned char *compr, size_t comprLen,
+ unsigned char *uncompr, size_t uncomprLen) {
+ PREFIX3(stream) c_stream; /* compression stream */
+ int err;
+
+ c_stream.zalloc = zalloc;
+ c_stream.zfree = zfree;
+ c_stream.opaque = (void *)0;
+
+ err = PREFIX(deflateInit)(&c_stream, Z_BEST_COMPRESSION);
+ CHECK_ERR(err, "deflateInit");
+
+ c_stream.next_out = compr;
+ c_stream.avail_out = (unsigned int)comprLen;
+
+ /* At this point, uncompr is still mostly zeroes, so it should compress
+ * very well:
+ */
+ c_stream.next_in = uncompr;
+ c_stream.avail_in = (unsigned int)uncomprLen;
+ err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate large 1");
+ if (c_stream.avail_in != 0) {
+ fprintf(stderr, "deflate not greedy\n");
+ exit(1);
+ }
+
+ /* Feed in already compressed data and switch to no compression: */
+ PREFIX(deflateParams)(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
+ c_stream.next_in = compr;
+ diff = (unsigned int)(c_stream.next_out - compr);
+ c_stream.avail_in = diff;
+ err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate large 2");
+
+ /* Switch back to compressing mode: */
+ PREFIX(deflateParams)(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
+ c_stream.next_in = uncompr;
+ c_stream.avail_in = (unsigned int)uncomprLen;
+ err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate large 3");
+
+ err = PREFIX(deflate)(&c_stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ fprintf(stderr, "deflate large should report Z_STREAM_END\n");
+ exit(1);
+ }
+ err = PREFIX(deflateEnd)(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with large buffers
+ */
+void test_large_inflate(unsigned char *compr, size_t comprLen,
+ unsigned char *uncompr, size_t uncomprLen) {
+ int err;
+ PREFIX3(stream) d_stream; /* decompression stream */
+
+ d_stream.zalloc = zalloc;
+ d_stream.zfree = zfree;
+ d_stream.opaque = (void *)0;
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = (unsigned int)comprLen;
+
+ err = PREFIX(inflateInit)(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ for (;;) {
+ d_stream.next_out = uncompr; /* discard the output */
+ d_stream.avail_out = (unsigned int)uncomprLen;
+ err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH);
+ if (err == Z_STREAM_END)
+ break;
+ CHECK_ERR(err, "large inflate");
+ }
+
+ err = PREFIX(inflateEnd)(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ if (d_stream.total_out != 2 * uncomprLen + diff) {
+ fprintf(stderr, "bad large inflate: %zu\n", d_stream.total_out);
+ exit(1);
+ }
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *d, size_t size) {
+ size_t comprLen = 100 + 3 * size;
+ size_t uncomprLen = comprLen;
+ uint8_t *compr, *uncompr;
+
+ /* Discard inputs larger than 512Kb. */
+ static size_t kMaxSize = 512 * 1024;
+
+ if (size < 1 || size > kMaxSize)
+ return 0;
+
+ data = d;
+ dataLen = size;
+ compr = (uint8_t *)calloc(1, comprLen);
+ uncompr = (uint8_t *)calloc(1, uncomprLen);
+
+ test_large_deflate(compr, comprLen, uncompr, uncomprLen);
+ test_large_inflate(compr, comprLen, uncompr, uncomprLen);
+
+ free(compr);
+ free(uncompr);
+
+ /* This function must return 0. */
+ return 0;
+}
--- /dev/null
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "zbuild.h"
+#ifdef ZLIB_COMPAT
+# include "zlib.h"
+#else
+# include "zlib-ng.h"
+#endif
+
+#define CHECK_ERR(err, msg) { \
+ if (err != Z_OK) { \
+ fprintf(stderr, "%s error: %d\n", msg, err); \
+ exit(1); \
+ } \
+}
+
+static const uint8_t *data;
+static size_t dataLen;
+static alloc_func zalloc = NULL;
+static free_func zfree = NULL;
+
+/* ===========================================================================
+ * Test deflate() with small buffers
+ */
+void test_deflate(unsigned char *compr, size_t comprLen) {
+ PREFIX3(stream) c_stream; /* compression stream */
+ int err;
+ unsigned long len = dataLen;
+
+ c_stream.zalloc = zalloc;
+ c_stream.zfree = zfree;
+ c_stream.opaque = (void *)0;
+
+ err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION);
+ CHECK_ERR(err, "deflateInit");
+
+ c_stream.next_in = (const unsigned char *)data;
+ c_stream.next_out = compr;
+
+ while (c_stream.total_in != len && c_stream.total_out < comprLen) {
+ c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
+ err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate small 1");
+ }
+ /* Finish the stream, still forcing small buffers: */
+ for (;;) {
+ c_stream.avail_out = 1;
+ err = PREFIX(deflate)(&c_stream, Z_FINISH);
+ if (err == Z_STREAM_END)
+ break;
+ CHECK_ERR(err, "deflate small 2");
+ }
+
+ err = PREFIX(deflateEnd)(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with small buffers
+ */
+void test_inflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr,
+ size_t uncomprLen) {
+ int err;
+ PREFIX3(stream) d_stream; /* decompression stream */
+
+ d_stream.zalloc = zalloc;
+ d_stream.zfree = zfree;
+ d_stream.opaque = (void *)0;
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = 0;
+ d_stream.next_out = uncompr;
+
+ err = PREFIX(inflateInit)(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
+ d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
+ err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH);
+ if (err == Z_STREAM_END)
+ break;
+ CHECK_ERR(err, "inflate");
+ }
+
+ err = PREFIX(inflateEnd)(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ if (memcmp(uncompr, data, dataLen)) {
+ fprintf(stderr, "bad inflate\n");
+ exit(1);
+ }
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *d, size_t size) {
+ size_t comprLen = PREFIX(compressBound)(size);
+ size_t uncomprLen = size;
+ uint8_t *compr, *uncompr;
+
+ /* Discard inputs larger than 1Mb. */
+ static size_t kMaxSize = 1024 * 1024;
+
+ if (size < 1 || size > kMaxSize)
+ return 0;
+
+ data = d;
+ dataLen = size;
+ compr = (uint8_t *)calloc(1, comprLen);
+ uncompr = (uint8_t *)calloc(1, uncomprLen);
+
+ test_deflate(compr, comprLen);
+ test_inflate(compr, comprLen, uncompr, uncomprLen);
+
+ free(compr);
+ free(uncompr);
+
+ /* This function must return 0. */
+ return 0;
+}
--- /dev/null
+/* minigzip.c -- simulate gzip using the zlib compression library
+ * Copyright (C) 1995-2006, 2010, 2011, 2016 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * minigzip is a minimal implementation of the gzip utility. This is
+ * only an example of using zlib and isn't meant to replace the
+ * full-featured gzip. No attempt is made to deal with file systems
+ * limiting names to 14 or 8+3 characters, etc... Error checking is
+ * very limited. So use minigzip only for testing; use gzip for the
+ * real thing.
+ */
+
+/* @(#) $Id$ */
+
+#include "zbuild.h"
+#ifdef ZLIB_COMPAT
+# include "zlib.h"
+#else
+# include "zlib-ng.h"
+#endif
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef USE_MMAP
+# include <sys/types.h>
+# include <sys/mman.h>
+# include <sys/stat.h>
+#endif
+
+#ifndef UNALIGNED_OK
+# include <malloc.h>
+#endif
+
+#if defined(WIN32) || defined(__CYGWIN__)
+# include <fcntl.h>
+# include <io.h>
+# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+#else
+# define SET_BINARY_MODE(file)
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER < 1900
+# define snprintf _snprintf
+#endif
+
+#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE)
+#ifndef WIN32 /* unlink already in stdio.h for WIN32 */
+ extern int unlink (const char *);
+#endif
+#endif
+
+#ifndef GZ_SUFFIX
+# define GZ_SUFFIX ".gz"
+#endif
+#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
+
+#define BUFLEN 16384 /* read buffer size */
+#define BUFLENW (BUFLEN * 3) /* write buffer size */
+#define MAX_NAME_LEN 1024
+
+#ifndef WITH_GZFILEOP
+/* without WITH_GZFILEOP, create simplified gz* functions using deflate and inflate */
+
+#if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE)
+# include <unistd.h> /* for unlink() */
+#endif
+
+void *myalloc (void *, unsigned, unsigned);
+void myfree (void *, void *);
+
+void *myalloc(void *q, unsigned n, unsigned m)
+{
+ (void)q;
+#ifndef UNALIGNED_OK
+ return memalign(16, n * m);
+#else
+ return calloc(n, m);
+#endif
+}
+
+void myfree(void *q, void *p)
+{
+ (void)q;
+ free(p);
+}
+
+typedef struct gzFile_s {
+ FILE *file;
+ int write;
+ int err;
+ const char *msg;
+ PREFIX3(stream) strm;
+ unsigned char *buf;
+} *gzFile;
+
+gzFile PREFIX(gzopen)(const char *, const char *);
+gzFile PREFIX(gzdopen)(int, const char *);
+gzFile gz_open (const char *, int, const char *);
+
+gzFile PREFIX(gzopen)(const char *path, const char *mode)
+{
+ return gz_open(path, -1, mode);
+}
+
+gzFile PREFIX(gzdopen)(int fd, const char *mode)
+{
+ return gz_open(NULL, fd, mode);
+}
+
+gzFile gz_open(const char *path, int fd, const char *mode)
+{
+ gzFile gz;
+ int ret;
+ int level = Z_DEFAULT_COMPRESSION;
+ const char *plevel = mode;
+
+ gz = malloc(sizeof(struct gzFile_s));
+ if (gz == NULL)
+ return NULL;
+ gz->write = strchr(mode, 'w') != NULL;
+ gz->strm.zalloc = myalloc;
+ gz->strm.zfree = myfree;
+ gz->strm.opaque = NULL;
+ gz->buf = malloc(gz->write ? BUFLENW : BUFLEN);
+
+ if (gz->buf == NULL) {
+ free(gz);
+ return NULL;
+ }
+
+ while (*plevel) {
+ if (*plevel >= '0' && *plevel <= '9') {
+ level = *plevel - '0';
+ break;
+ }
+ plevel++;
+ }
+ if (gz->write)
+ ret = PREFIX(deflateInit2)(&(gz->strm), level, 8, 15 + 16, 8, 0);
+ else {
+ gz->strm.next_in = NULL;
+ gz->strm.avail_in = 0;
+ ret = PREFIX(inflateInit2)(&(gz->strm), 15 + 16);
+ }
+ if (ret != Z_OK) {
+ free(gz);
+ return NULL;
+ }
+ gz->file = path == NULL ? fdopen(fd, gz->write ? "wb" : "rb") :
+ fopen(path, gz->write ? "wb" : "rb");
+ if (gz->file == NULL) {
+ gz->write ? PREFIX(deflateEnd)(&(gz->strm)) : PREFIX(inflateEnd)(&(gz->strm));
+ free(gz);
+ return NULL;
+ }
+ gz->err = 0;
+ gz->msg = "";
+ return gz;
+}
+
+int PREFIX(gzwrite)(gzFile, const void *, unsigned);
+
+int PREFIX(gzwrite)(gzFile gz, const void *buf, unsigned len)
+{
+ PREFIX3(stream) *strm;
+
+ if (gz == NULL || !gz->write)
+ return 0;
+ strm = &(gz->strm);
+ strm->next_in = (void *)buf;
+ strm->avail_in = len;
+ do {
+ strm->next_out = gz->buf;
+ strm->avail_out = BUFLENW;
+ (void)PREFIX(deflate)(strm, Z_NO_FLUSH);
+ fwrite(gz->buf, 1, BUFLENW - strm->avail_out, gz->file);
+ } while (strm->avail_out == 0);
+ return len;
+}
+
+int PREFIX(gzread)(gzFile, void *, unsigned);
+
+int PREFIX(gzread)(gzFile gz, void *buf, unsigned len)
+{
+ PREFIX3(stream) *strm;
+
+ if (gz == NULL || gz->write || gz->err)
+ return 0;
+ strm = &(gz->strm);
+ strm->next_out = buf;
+ strm->avail_out = len;
+ do {
+ if (strm->avail_in == 0)
+ {
+ strm->next_in = gz->buf;
+ strm->avail_in = (uint32_t)fread(gz->buf, 1, BUFLEN, gz->file);
+ }
+ if (strm->avail_in > 0)
+ {
+ int ret = PREFIX(inflate)(strm, Z_NO_FLUSH);
+ if (ret == Z_DATA_ERROR) {
+ gz->err = ret;
+ gz->msg = strm->msg;
+ return 0;
+ }
+ else if (ret == Z_STREAM_END)
+ PREFIX(inflateReset)(strm);
+ }
+ else
+ break;
+ } while (strm->avail_out);
+ return len - strm->avail_out;
+}
+
+int PREFIX(gzclose)(gzFile);
+
+int PREFIX(gzclose)(gzFile gz)
+{
+ PREFIX3(stream) *strm;
+
+ if (gz == NULL)
+ return Z_STREAM_ERROR;
+ strm = &(gz->strm);
+ if (gz->write) {
+ strm->next_in = NULL;
+ strm->avail_in = 0;
+ do {
+ strm->next_out = gz->buf;
+ strm->avail_out = BUFLENW;
+ (void)PREFIX(deflate)(strm, Z_FINISH);
+ fwrite(gz->buf, 1, BUFLENW - strm->avail_out, gz->file);
+ } while (strm->avail_out == 0);
+ PREFIX(deflateEnd)(strm);
+ }
+ else
+ PREFIX(inflateEnd)(strm);
+ free(gz->buf);
+ fclose(gz->file);
+ free(gz);
+ return Z_OK;
+}
+
+const char *PREFIX(gzerror)(gzFile, int *);
+
+const char *PREFIX(gzerror)(gzFile gz, int *err)
+{
+ *err = gz->err;
+ return gz->msg;
+}
+
+#endif
+
+static char *prog;
+
+void error (const char *msg);
+void gz_compress (FILE *in, gzFile out);
+#ifdef USE_MMAP
+int gz_compress_mmap (FILE *in, gzFile out);
+#endif
+void gz_uncompress (gzFile in, FILE *out);
+void file_compress (char *file, char *mode);
+void file_uncompress (char *file);
+int main (int argc, char *argv[]);
+
+/* ===========================================================================
+ * Display error message and exit
+ */
+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(FILE *in, gzFile out)
+{
+ 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
+ /* Clear out the contents of buf before reading from the file to avoid
+ MemorySanitizer: use-of-uninitialized-value warnings. */
+ memset(buf, 0, sizeof(buf));
+ for (;;) {
+ len = (int)fread(buf, 1, sizeof(buf), in);
+ if (ferror(in)) {
+ perror("fread");
+ exit(1);
+ }
+ if (len == 0) break;
+
+ if (PREFIX(gzwrite)(out, buf, (unsigned)len) != len) error(PREFIX(gzerror)(out, &err));
+ }
+ fclose(in);
+ if (PREFIX(gzclose)(out) != Z_OK) error("failed gzclose");
+}
+
+#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */
+
+/* Try compressing the input file at once using mmap. Return Z_OK if
+ * if success, Z_ERRNO otherwise.
+ */
+int gz_compress_mmap(FILE *in, gzFile out)
+{
+ int len;
+ int err;
+ int ifd = fileno(in);
+ caddr_t buf; /* mmap'ed buffer for the entire input file */
+ off_t buf_len; /* length of the input file */
+ struct stat sb;
+
+ /* Determine the size of the file, needed for mmap: */
+ if (fstat(ifd, &sb) < 0) return Z_ERRNO;
+ buf_len = sb.st_size;
+ if (buf_len <= 0) return Z_ERRNO;
+
+ /* Now do the actual mmap: */
+ buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);
+ if (buf == (caddr_t)(-1)) return Z_ERRNO;
+
+ /* Compress the whole file at once: */
+ len = PREFIX(gzwrite)(out, (char *)buf, (unsigned)buf_len);
+
+ if (len != (int)buf_len) error(PREFIX(gzerror)(out, &err));
+
+ munmap(buf, buf_len);
+ fclose(in);
+ if (PREFIX(gzclose)(out) != Z_OK) error("failed gzclose");
+ return Z_OK;
+}
+#endif /* USE_MMAP */
+
+/* ===========================================================================
+ * Uncompress input to output then close both files.
+ */
+void gz_uncompress(gzFile in, FILE *out)
+{
+ char buf[BUFLENW];
+ int len;
+ int err;
+
+ for (;;) {
+ len = PREFIX(gzread)(in, buf, sizeof(buf));
+ if (len < 0) error (PREFIX(gzerror)(in, &err));
+ if (len == 0) break;
+
+ if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
+ error("failed fwrite");
+ }
+ }
+ if (fclose(out)) error("failed fclose");
+
+ if (PREFIX(gzclose)(in) != Z_OK) error("failed gzclose");
+}
+
+
+/* ===========================================================================
+ * Compress the given file: create a corresponding .gz file and remove the
+ * original.
+ */
+void file_compress(char *file, char *mode)
+{
+ char outfile[MAX_NAME_LEN];
+ FILE *in;
+ gzFile out;
+
+ if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) {
+ fprintf(stderr, "%s: filename too long\n", prog);
+ exit(1);
+ }
+
+ snprintf(outfile, sizeof(outfile), "%s%s", file, GZ_SUFFIX);
+
+ in = fopen(file, "rb");
+ if (in == NULL) {
+ perror(file);
+ exit(1);
+ }
+ out = PREFIX(gzopen)(outfile, mode);
+ if (out == NULL) {
+ fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
+ exit(1);
+ }
+ gz_compress(in, out);
+
+ unlink(file);
+}
+
+
+/* ===========================================================================
+ * Uncompress the given file and remove the original.
+ */
+void file_uncompress(char *file)
+{
+ char buf[MAX_NAME_LEN];
+ char *infile, *outfile;
+ FILE *out;
+ gzFile in;
+ size_t len = strlen(file);
+
+ if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) {
+ fprintf(stderr, "%s: filename too long\n", prog);
+ exit(1);
+ }
+
+ snprintf(buf, sizeof(buf), "%s", file);
+
+ if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
+ infile = file;
+ outfile = buf;
+ outfile[len-3] = '\0';
+ } else {
+ outfile = file;
+ infile = buf;
+ snprintf(buf + len, sizeof(buf) - len, "%s", GZ_SUFFIX);
+ }
+ in = PREFIX(gzopen)(infile, "rb");
+ if (in == NULL) {
+ fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
+ exit(1);
+ }
+ out = fopen(outfile, "wb");
+ if (out == NULL) {
+ perror(file);
+ exit(1);
+ }
+
+ gz_uncompress(in, out);
+
+ unlink(infile);
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataLen) {
+ char *inFileName = "/tmp/minigzip_fuzzer.out";
+ char *outFileName = "/tmp/minigzip_fuzzer.out.gz";
+ char outmode[20];
+ FILE *in;
+ char buf[BUFLEN];
+ uint32_t offset = 0;
+
+ /* Discard inputs larger than 1Mb. */
+ static size_t kMaxSize = 1024 * 1024;
+ if (dataLen < 1 || dataLen > kMaxSize)
+ return 0;
+
+ in = fopen(inFileName, "w");
+ if (fwrite(data, 1, (unsigned)dataLen, in) != dataLen)
+ error("failed fwrite");
+ if (fclose(in))
+ error("failed fclose");
+
+ memset(outmode, 0, sizeof(outmode));
+ snprintf(outmode, sizeof(outmode), "%s", "wb");
+
+ /* Compression level: [0..9]. */
+ outmode[2] = data[0] % 10;
+
+ switch (data[0] % 4) {
+ default:
+ case 0:
+ outmode[3] = 0;
+ break;
+ case 1:
+ /* compress with Z_FILTERED */
+ outmode[3] = 'f';
+ break;
+ case 2:
+ /* compress with Z_HUFFMAN_ONLY */
+ outmode[3] = 'h';
+ break;
+ case 3:
+ /* compress with Z_RLE */
+ outmode[3] = 'R';
+ break;
+ }
+
+ file_compress(inFileName, outmode);
+ file_uncompress(outFileName);
+
+ /* Check that the uncompressed file matches the input data. */
+ in = fopen(inFileName, "rb");
+ if (in == NULL) {
+ perror(inFileName);
+ exit(1);
+ }
+
+ memset(buf, 0, sizeof(buf));
+ for (;;) {
+ int len = (int)fread(buf, 1, sizeof(buf), in);
+ if (ferror(in)) {
+ perror("fread");
+ exit(1);
+ }
+ if (len == 0)
+ break;
+ assert(0 == memcmp(data + offset, buf, len));
+ offset += len;
+ }
+
+ if (fclose(in))
+ error("failed fclose");
+
+ /* This function must return 0. */
+ return 0;
+}
--- /dev/null
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size);
+
+int main(int argc, char **argv) {
+ int i;
+ fprintf(stderr, "StandaloneFuzzTargetMain: running %d inputs\n", argc - 1);
+
+ for (i = 1; i < argc; i++) {
+ size_t len, n_read, err;
+ unsigned char *buf;
+ FILE *f = fopen(argv[i], "r+");
+ if (!f) {
+ /* Failed to open this file: it may be a directory. */
+ fprintf(stderr, "Skipping: %s\n", argv[i]);
+ continue;
+ }
+ fprintf(stderr, "Running: %s %s\n", argv[0], argv[i]);
+ fseek(f, 0, SEEK_END);
+ len = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ buf = (unsigned char *)malloc(len);
+ n_read = fread(buf, 1, len, f);
+ assert(n_read == len);
+ LLVMFuzzerTestOneInput(buf, len);
+ free(buf);
+ err = fclose(f);
+ assert(err == 0);
+ fprintf(stderr, "Done: %s: (%d bytes)\n", argv[i], (int)n_read);
+ }
+
+ return 0;
+}