• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <fuzzer/FuzzedDataProvider.h>
16 
17 #include <cstdint>
18 #include <cstdio>
19 #include <cstdlib>
20 #include <memory>
21 #include <vector>
22 
23 #include "lzo1.h"
24 #include "lzo1a.h"
25 #include "lzo1b.h"
26 #include "lzo1c.h"
27 #include "lzo1f.h"
28 #include "lzo1x.h"
29 #include "lzo1y.h"
30 #include "lzo1z.h"
31 #include "lzo2a.h"
32 #include "lzoconf.h"
33 
34 namespace {
35 
36 struct LzoAlgorithm {
37   enum class Category { LZO1, LZO2 };
38   enum class Type {
39     LZO1,
40     LZO1A,
41     LZO1B,
42     LZO1C,
43     LZO1F,
44     LZO1X,
45     LZO1Y,
46     LZO1Z,
47     LZO2A
48   };
49 
LzoAlgorithm__anonc6b672860111::LzoAlgorithm50   constexpr LzoAlgorithm(Category category, Type type, int compression_level,
51                          int memory_level, lzo_compress_t compress_fn,
52                          lzo_decompress_t decompress_fn,
53                          size_t working_memory_size)
54       : category(category),
55         type(type),
56         compression_level(compression_level),
57         memory_level(memory_level),
58         compress_fn(compress_fn),
59         decompress_fn(decompress_fn),
60         working_memory_size(working_memory_size) {}
61 
GetMaxCompressedSize__anonc6b672860111::LzoAlgorithm62   size_t GetMaxCompressedSize(size_t size) const {
63     // Formula taken from the LZO FAQ.
64     switch (category) {
65       case Category::LZO1:
66         return size + (size / 16) + 64 + 3;
67       case Category::LZO2:
68         return size + (size / 8) + 128 + 3;
69     }
70   }
71 
72   Category category;
73   Type type;
74   int compression_level;
75   int memory_level;
76 
77   lzo_compress_t compress_fn;
78   lzo_decompress_t decompress_fn;
79   size_t working_memory_size;
80 };
81 
GetLzoAlgorithms()82 static const std::vector<std::vector<LzoAlgorithm>>& GetLzoAlgorithms() {
83   static auto* algorithms = new std::vector<std::vector<LzoAlgorithm>>{
84       {
85           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1,
86                        0, 0, lzo1_compress, lzo1_decompress, LZO1_MEM_COMPRESS),
87           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1,
88                        99, 0, lzo1_99_compress, lzo1_decompress,
89                        LZO1_99_MEM_COMPRESS),
90       },
91       {
92           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1A,
93                        0, 0, lzo1a_compress, lzo1a_decompress,
94                        LZO1A_MEM_COMPRESS),
95           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1A,
96                        99, 0, lzo1a_99_compress, lzo1a_decompress,
97                        LZO1A_99_MEM_COMPRESS),
98       },
99       {
100           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
101                        1, 0, lzo1b_1_compress, lzo1b_decompress,
102                        LZO1B_MEM_COMPRESS),
103           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
104                        2, 0, lzo1b_2_compress, lzo1b_decompress,
105                        LZO1B_MEM_COMPRESS),
106           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
107                        3, 0, lzo1b_3_compress, lzo1b_decompress,
108                        LZO1B_MEM_COMPRESS),
109           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
110                        4, 0, lzo1b_4_compress, lzo1b_decompress,
111                        LZO1B_MEM_COMPRESS),
112           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
113                        5, 0, lzo1b_5_compress, lzo1b_decompress,
114                        LZO1B_MEM_COMPRESS),
115           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
116                        6, 0, lzo1b_6_compress, lzo1b_decompress,
117                        LZO1B_MEM_COMPRESS),
118           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
119                        7, 0, lzo1b_7_compress, lzo1b_decompress,
120                        LZO1B_MEM_COMPRESS),
121           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
122                        8, 0, lzo1b_8_compress, lzo1b_decompress,
123                        LZO1B_MEM_COMPRESS),
124           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
125                        9, 0, lzo1b_9_compress, lzo1b_decompress,
126                        LZO1B_MEM_COMPRESS),
127           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
128                        99, 0, lzo1b_99_compress, lzo1b_decompress,
129                        LZO1B_99_MEM_COMPRESS),
130           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
131                        999, 0, lzo1b_999_compress, lzo1b_decompress,
132                        LZO1B_999_MEM_COMPRESS),
133       },
134       {
135           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1C,
136                        1, 0, lzo1c_1_compress, lzo1c_decompress,
137                        LZO1C_MEM_COMPRESS),
138           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1C,
139                        5, 0, lzo1c_5_compress, lzo1c_decompress,
140                        LZO1C_MEM_COMPRESS),
141           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1C,
142                        9, 0, lzo1c_9_compress, lzo1c_decompress,
143                        LZO1C_MEM_COMPRESS),
144           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1C,
145                        99, 0, lzo1c_99_compress, lzo1c_decompress,
146                        LZO1C_99_MEM_COMPRESS),
147           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1C,
148                        999, 0, lzo1c_999_compress, lzo1c_decompress,
149                        LZO1C_999_MEM_COMPRESS),
150       },
151       {
152           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1F,
153                        1, 0, lzo1f_1_compress, lzo1f_decompress,
154                        LZO1F_MEM_COMPRESS),
155           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1F,
156                        999, 0, lzo1f_999_compress, lzo1f_decompress,
157                        LZO1F_999_MEM_COMPRESS),
158       },
159       {
160           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1X,
161                        1, 0, lzo1x_1_compress, lzo1x_decompress,
162                        LZO1X_1_MEM_COMPRESS),
163           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1X,
164                        1, 11, lzo1x_1_11_compress, lzo1x_decompress,
165                        LZO1X_1_11_MEM_COMPRESS),
166           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1X,
167                        1, 12, lzo1x_1_12_compress, lzo1x_decompress,
168                        LZO1X_1_12_MEM_COMPRESS),
169           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1X,
170                        1, 15, lzo1x_1_15_compress, lzo1x_decompress,
171                        LZO1X_1_15_MEM_COMPRESS),
172           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1X,
173                        999, 0, lzo1x_999_compress, lzo1x_decompress,
174                        LZO1X_999_MEM_COMPRESS),
175       },
176       {
177           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1Y,
178                        1, 0, lzo1y_1_compress, lzo1y_decompress,
179                        LZO1Y_MEM_COMPRESS),
180           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1Y,
181                        999, 0, lzo1y_999_compress, lzo1y_decompress,
182                        LZO1Y_999_MEM_COMPRESS),
183       },
184       {
185           LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1Z,
186                        999, 0, lzo1z_999_compress, lzo1z_decompress,
187                        LZO1Z_999_MEM_COMPRESS),
188       },
189       {
190           LzoAlgorithm(LzoAlgorithm::Category::LZO2, LzoAlgorithm::Type::LZO2A,
191                        999, 0, lzo2a_999_compress, lzo2a_decompress,
192                        LZO2A_999_MEM_COMPRESS),
193       },
194   };
195   return *algorithms;
196 }
197 
FuzzLzoAlgorithm(const LzoAlgorithm & algorithm,const std::vector<uint8_t> & input_buffer)198 void FuzzLzoAlgorithm(const LzoAlgorithm& algorithm,
199                       const std::vector<uint8_t>& input_buffer) {
200   std::unique_ptr<uint8_t[]> working_buffer(
201       new uint8_t[algorithm.working_memory_size]);
202   std::unique_ptr<uint8_t[]> compressed_buffer(
203       new uint8_t[algorithm.GetMaxCompressedSize(input_buffer.size())]);
204 
205   lzo_uint compressed_size;
206   if (algorithm.compress_fn(input_buffer.data(), input_buffer.size(),
207                             compressed_buffer.get(), &compressed_size,
208                             working_buffer.get()) != LZO_E_OK) {
209     abort();
210   }
211 
212   std::unique_ptr<uint8_t[]> decompressed_buffer(
213       new uint8_t[input_buffer.size()]);
214   lzo_uint decompressed_size;
215   if (algorithm.decompress_fn(compressed_buffer.get(), compressed_size,
216                               decompressed_buffer.get(), &decompressed_size,
217                               nullptr) != LZO_E_OK) {
218     abort();
219   }
220 
221   if (decompressed_size != input_buffer.size()) {
222     fprintf(stderr, "Decompressed size %zu does not match original size %zu.\n",
223             decompressed_size, input_buffer.size());
224     abort();
225   } else if (memcmp(input_buffer.data(), decompressed_buffer.get(),
226                     input_buffer.size()) != 0) {
227     fprintf(stderr,
228             "Decompressed buffer does not match original buffer of size %zu.\n",
229             input_buffer.size());
230     abort();
231   }
232 }
233 
234 }  // namespace
235 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)236 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
237   static bool initialized __attribute__((unused)) = []() {
238     if (lzo_init() != LZO_E_OK) {
239       abort();
240     }
241     return true;
242   }();
243 
244   FuzzedDataProvider data_provider(data, size);
245   const auto& algorithms = GetLzoAlgorithms();
246   const auto first_level_index =
247       data_provider.ConsumeIntegralInRange<size_t>(0, algorithms.size() - 1);
248   const auto& algorithm_group = algorithms[first_level_index];
249   const auto second_level_index = data_provider.ConsumeIntegralInRange<size_t>(
250       0, algorithm_group.size() - 1);
251   const std::vector<uint8_t> input_buffer =
252       data_provider.ConsumeRemainingBytes<uint8_t>();
253   FuzzLzoAlgorithm(algorithm_group[second_level_index], input_buffer);
254   return 0;
255 }
256