1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <memory.h>
6 #include <stddef.h>
7 #include <stdint.h>
8 #include <stdlib.h>
9 
10 #include <fuzzer/FuzzedDataProvider.h>
11 
12 #include <vector>
13 
14 #include "base/scoped_generic.h"
15 #include "third_party/minizip/src/mz.h"
16 #include "third_party/minizip/src/mz_strm_mem.h"
17 #include "third_party/minizip/src/mz_zip.h"
18 
19 const char kTestFileName[] = "test.zip";
20 
21 namespace {
22 
23 struct MzTraitsBase {
InvalidValue__anon8956152c0111::MzTraitsBase24   static void* InvalidValue() { return nullptr; }
25 };
26 
27 struct MzStreamMemTraits : public MzTraitsBase {
Free__anon8956152c0111::MzStreamMemTraits28   static void Free(void* stream) { mz_stream_mem_delete(&stream); }
29 };
30 typedef base::ScopedGeneric<void*, MzStreamMemTraits> ScopedMzStreamMem;
31 
32 struct MzZipTraits : public MzTraitsBase {
Free__anon8956152c0111::MzZipTraits33   static void Free(void* stream) {
34     mz_zip_close(stream);
35     mz_zip_delete(&stream);
36   }
37 };
38 typedef base::ScopedGeneric<void*, MzZipTraits> ScopedMzZip;
39 
40 }  // namespace
41 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)42 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
43   FuzzedDataProvider data_provider(data, size);
44 
45   mz_zip_file file_info = {};
46   file_info.flag = MZ_ZIP_FLAG_UTF8;
47   if (data_provider.ConsumeIntegral<uint8_t>() < 0x08) {
48     file_info.flag = data_provider.ConsumeIntegral<uint16_t>();
49   }
50   file_info.compression_method = MZ_COMPRESS_METHOD_DEFLATE;
51   if (data_provider.ConsumeIntegral<uint8_t>() < 0x08) {
52     file_info.compression_method = MZ_COMPRESS_METHOD_STORE;
53   } else if (data_provider.ConsumeIntegral<uint8_t>() < 0x08) {
54     file_info.compression_method = data_provider.ConsumeIntegral<uint16_t>();
55   }
56   if (data_provider.ConsumeIntegral<uint8_t>() < 0x08) {
57     file_info.zip64 = data_provider.ConsumeIntegral<uint16_t>();
58   }
59   file_info.filename = kTestFileName;
60   file_info.filename_size = sizeof(kTestFileName);
61 
62   int16_t compress_level = MZ_COMPRESS_LEVEL_DEFAULT;
63   if (data_provider.ConsumeIntegral<uint8_t>() < 0x08) {
64     compress_level =
65         static_cast<int16_t>(data_provider.ConsumeIntegral<uint16_t>());
66   }
67 
68   ScopedMzStreamMem out_stream(mz_stream_mem_create(nullptr));
69 
70   ScopedMzZip zip_file(mz_zip_create(nullptr));
71   int result = mz_zip_open(zip_file.get(), out_stream.get(),
72                            MZ_OPEN_MODE_CREATE | MZ_OPEN_MODE_WRITE);
73   if (result != MZ_OK) {
74     return 0;
75   }
76 
77   result = mz_zip_entry_write_open(zip_file.get(), &file_info, compress_level,
78                                    0, nullptr);
79   if (result != MZ_OK) {
80     return 0;
81   }
82 
83   std::vector<uint8_t> remaining_data =
84       data_provider.ConsumeRemainingBytes<uint8_t>();
85   result = mz_zip_entry_write(zip_file.get(), remaining_data.data(),
86                               remaining_data.size());
87   if (result != MZ_OK) {
88     return 0;
89   }
90 
91   result = mz_zip_entry_close(zip_file.get());
92   if (result != MZ_OK) {
93     return 0;
94   }
95 
96   result = mz_zip_close(zip_file.get());
97   if (result != MZ_OK) {
98     return 0;
99   }
100 
101   return 0;
102 }
103