/* zip_fuzzer.c - Zip fuzzer for libFuzzer part of the minizip-ng project Copyright (C) 2018 The Chromium Authors Copyright (C) 2018 Anand K. Mistry Copyright (C) Nathan Moinvaziri https://github.com/zlib-ng/minizip-ng This program is distributed under the terms of the same license as zlib. See the accompanying LICENSE file for the full text of the license. */ #include "mz.h" #include "mz_strm.h" #include "mz_strm_mem.h" #include "mz_zip.h" #ifdef __cplusplus extern "C" { #endif /***************************************************************************/ #define MZ_FUZZ_TEST_FILENAME "foo" #define MZ_FUZZ_TEST_PWD "test123" /***************************************************************************/ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { mz_zip_file file_info; void *fuzz_stream = NULL; void *stream = NULL; void *handle = NULL; int32_t err = MZ_OK; uint16_t value16 = 0; uint8_t value8 = 0; int16_t compress_level = 0; int64_t fuzz_pos = 0; int32_t fuzz_length = 0; uint8_t *fuzz_buf = NULL; const char *password = NULL; fuzz_stream = mz_stream_mem_create(); if (!fuzz_stream) return 1; mz_stream_mem_set_buffer(fuzz_stream, (void *)data, (int32_t)size); memset(&file_info, 0, sizeof(file_info)); file_info.flag = MZ_ZIP_FLAG_UTF8; if ((mz_stream_read_uint8(fuzz_stream, &value8) == MZ_OK) && (value8 < 0x08)) { if (mz_stream_read_uint16(fuzz_stream, &value16) == MZ_OK) file_info.flag = value16; } file_info.compression_method = MZ_COMPRESS_METHOD_DEFLATE; if ((mz_stream_read_uint8(fuzz_stream, &value8) == MZ_OK) && (value8 < 0x08)) { file_info.compression_method = MZ_COMPRESS_METHOD_STORE; } else if ((mz_stream_read_uint8(fuzz_stream, &value8) == MZ_OK) && (value8 < 0x08)) { if (mz_stream_read_uint16(fuzz_stream, &value16) == MZ_OK) file_info.compression_method = value16; } if ((mz_stream_read_uint8(fuzz_stream, &value8) == MZ_OK) && (value8 < 0x08)) { if (mz_stream_read_uint16(fuzz_stream, &value16) == MZ_OK) file_info.zip64 = value16; } file_info.filename = MZ_FUZZ_TEST_FILENAME; file_info.filename_size = (uint16_t)strlen(MZ_FUZZ_TEST_FILENAME); compress_level = MZ_COMPRESS_LEVEL_DEFAULT; if ((mz_stream_read_uint8(fuzz_stream, &value8) == MZ_OK) && (value8 < 0x08)) { if (mz_stream_read_uint16(fuzz_stream, &value16) == MZ_OK) compress_level = value16; } stream = mz_stream_mem_create(); if (!stream) { mz_stream_mem_delete(&fuzz_stream); return 1; } err = mz_stream_mem_open(stream, MZ_FUZZ_TEST_FILENAME, MZ_OPEN_MODE_CREATE | MZ_OPEN_MODE_WRITE); if (err != MZ_OK) { mz_stream_mem_delete(&stream); mz_stream_mem_delete(&fuzz_stream); return 1; } handle = mz_zip_create(); if (!handle) { mz_stream_mem_delete(&stream); mz_stream_mem_delete(&fuzz_stream); return 1; } err = mz_zip_open(handle, stream, MZ_OPEN_MODE_CREATE | MZ_OPEN_MODE_WRITE); if (err == MZ_OK) { password = file_info.flag & MZ_ZIP_FLAG_ENCRYPTED ? MZ_FUZZ_TEST_PWD : NULL; err = mz_zip_entry_write_open(handle, &file_info, compress_level, 0, password); if (err == MZ_OK) { mz_stream_mem_get_buffer_at_current(fuzz_stream, (const void **)&fuzz_buf); fuzz_pos = mz_stream_tell(fuzz_stream); mz_stream_mem_get_buffer_length(fuzz_stream, &fuzz_length); err = mz_zip_entry_write(handle, fuzz_buf, (fuzz_length - (int32_t)fuzz_pos)); mz_zip_entry_close(handle); } mz_zip_close(handle); } mz_zip_delete(&handle); mz_stream_mem_delete(&stream); mz_stream_mem_delete(&fuzz_stream); return 0; } /***************************************************************************/ #ifdef __cplusplus } #endif