Coverage Report

Created: 2023-09-25 06:16

/src/all_lzo_compress.cc
Line
Count
Source (jump to first uncovered line)
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
50
  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
0
        working_memory_size(working_memory_size) {}
61
62
19.0k
  size_t GetMaxCompressedSize(size_t size) const {
63
    // Formula taken from the LZO FAQ.
64
19.0k
    switch (category) {
65
18.2k
      case Category::LZO1:
66
18.2k
        return size + (size / 16) + 64 + 3;
67
821
      case Category::LZO2:
68
821
        return size + (size / 8) + 128 + 3;
69
19.0k
    }
70
19.0k
  }
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
82
19.0k
static const std::vector<std::vector<LzoAlgorithm>>& GetLzoAlgorithms() {
83
19.0k
  static auto* algorithms = new std::vector<std::vector<LzoAlgorithm>>{
84
19.0k
      {
85
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1,
86
19.0k
                       0, 0, lzo1_compress, lzo1_decompress, LZO1_MEM_COMPRESS),
87
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1,
88
19.0k
                       99, 0, lzo1_99_compress, lzo1_decompress,
89
19.0k
                       LZO1_99_MEM_COMPRESS),
90
19.0k
      },
91
19.0k
      {
92
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1A,
93
19.0k
                       0, 0, lzo1a_compress, lzo1a_decompress,
94
19.0k
                       LZO1A_MEM_COMPRESS),
95
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1A,
96
19.0k
                       99, 0, lzo1a_99_compress, lzo1a_decompress,
97
19.0k
                       LZO1A_99_MEM_COMPRESS),
98
19.0k
      },
99
19.0k
      {
100
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
101
19.0k
                       1, 0, lzo1b_1_compress, lzo1b_decompress,
102
19.0k
                       LZO1B_MEM_COMPRESS),
103
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
104
19.0k
                       2, 0, lzo1b_2_compress, lzo1b_decompress,
105
19.0k
                       LZO1B_MEM_COMPRESS),
106
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
107
19.0k
                       3, 0, lzo1b_3_compress, lzo1b_decompress,
108
19.0k
                       LZO1B_MEM_COMPRESS),
109
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
110
19.0k
                       4, 0, lzo1b_4_compress, lzo1b_decompress,
111
19.0k
                       LZO1B_MEM_COMPRESS),
112
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
113
19.0k
                       5, 0, lzo1b_5_compress, lzo1b_decompress,
114
19.0k
                       LZO1B_MEM_COMPRESS),
115
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
116
19.0k
                       6, 0, lzo1b_6_compress, lzo1b_decompress,
117
19.0k
                       LZO1B_MEM_COMPRESS),
118
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
119
19.0k
                       7, 0, lzo1b_7_compress, lzo1b_decompress,
120
19.0k
                       LZO1B_MEM_COMPRESS),
121
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
122
19.0k
                       8, 0, lzo1b_8_compress, lzo1b_decompress,
123
19.0k
                       LZO1B_MEM_COMPRESS),
124
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
125
19.0k
                       9, 0, lzo1b_9_compress, lzo1b_decompress,
126
19.0k
                       LZO1B_MEM_COMPRESS),
127
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
128
19.0k
                       99, 0, lzo1b_99_compress, lzo1b_decompress,
129
19.0k
                       LZO1B_99_MEM_COMPRESS),
130
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
131
19.0k
                       999, 0, lzo1b_999_compress, lzo1b_decompress,
132
19.0k
                       LZO1B_999_MEM_COMPRESS),
133
19.0k
      },
134
19.0k
      {
135
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1C,
136
19.0k
                       1, 0, lzo1c_1_compress, lzo1c_decompress,
137
19.0k
                       LZO1C_MEM_COMPRESS),
138
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1C,
139
19.0k
                       5, 0, lzo1c_5_compress, lzo1c_decompress,
140
19.0k
                       LZO1C_MEM_COMPRESS),
141
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1C,
142
19.0k
                       9, 0, lzo1c_9_compress, lzo1c_decompress,
143
19.0k
                       LZO1C_MEM_COMPRESS),
144
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1C,
145
19.0k
                       99, 0, lzo1c_99_compress, lzo1c_decompress,
146
19.0k
                       LZO1C_99_MEM_COMPRESS),
147
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1C,
148
19.0k
                       999, 0, lzo1c_999_compress, lzo1c_decompress,
149
19.0k
                       LZO1C_999_MEM_COMPRESS),
150
19.0k
      },
151
19.0k
      {
152
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1F,
153
19.0k
                       1, 0, lzo1f_1_compress, lzo1f_decompress,
154
19.0k
                       LZO1F_MEM_COMPRESS),
155
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1F,
156
19.0k
                       999, 0, lzo1f_999_compress, lzo1f_decompress,
157
19.0k
                       LZO1F_999_MEM_COMPRESS),
158
19.0k
      },
159
19.0k
      {
160
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1X,
161
19.0k
                       1, 0, lzo1x_1_compress, lzo1x_decompress,
162
19.0k
                       LZO1X_1_MEM_COMPRESS),
163
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1X,
164
19.0k
                       1, 11, lzo1x_1_11_compress, lzo1x_decompress,
165
19.0k
                       LZO1X_1_11_MEM_COMPRESS),
166
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1X,
167
19.0k
                       1, 12, lzo1x_1_12_compress, lzo1x_decompress,
168
19.0k
                       LZO1X_1_12_MEM_COMPRESS),
169
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1X,
170
19.0k
                       1, 15, lzo1x_1_15_compress, lzo1x_decompress,
171
19.0k
                       LZO1X_1_15_MEM_COMPRESS),
172
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1X,
173
19.0k
                       999, 0, lzo1x_999_compress, lzo1x_decompress,
174
19.0k
                       LZO1X_999_MEM_COMPRESS),
175
19.0k
      },
176
19.0k
      {
177
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1Y,
178
19.0k
                       1, 0, lzo1y_1_compress, lzo1y_decompress,
179
19.0k
                       LZO1Y_MEM_COMPRESS),
180
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1Y,
181
19.0k
                       999, 0, lzo1y_999_compress, lzo1y_decompress,
182
19.0k
                       LZO1Y_999_MEM_COMPRESS),
183
19.0k
      },
184
19.0k
      {
185
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1Z,
186
19.0k
                       999, 0, lzo1z_999_compress, lzo1z_decompress,
187
19.0k
                       LZO1Z_999_MEM_COMPRESS),
188
19.0k
      },
189
19.0k
      {
190
19.0k
          LzoAlgorithm(LzoAlgorithm::Category::LZO2, LzoAlgorithm::Type::LZO2A,
191
19.0k
                       999, 0, lzo2a_999_compress, lzo2a_decompress,
192
19.0k
                       LZO2A_999_MEM_COMPRESS),
193
19.0k
      },
194
19.0k
  };
195
19.0k
  return *algorithms;
196
19.0k
}
197
198
void FuzzLzoAlgorithm(const LzoAlgorithm& algorithm,
199
19.0k
                      const std::vector<uint8_t>& input_buffer) {
200
19.0k
  std::unique_ptr<uint8_t[]> working_buffer(
201
19.0k
      new uint8_t[algorithm.working_memory_size]);
202
19.0k
  std::unique_ptr<uint8_t[]> compressed_buffer(
203
19.0k
      new uint8_t[algorithm.GetMaxCompressedSize(input_buffer.size())]);
204
205
#if MEMORY_SANITIZER
206
  __msan_unpoison(working_buffer.get(), algorithm.working_memory_size);
207
#endif
208
209
19.0k
  lzo_uint compressed_size;
210
19.0k
  if (algorithm.compress_fn(input_buffer.data(), input_buffer.size(),
211
19.0k
                            compressed_buffer.get(), &compressed_size,
212
19.0k
                            working_buffer.get()) != LZO_E_OK) {
213
0
    abort();
214
0
  }
215
216
19.0k
  std::unique_ptr<uint8_t[]> decompressed_buffer(
217
19.0k
      new uint8_t[input_buffer.size()]);
218
19.0k
  lzo_uint decompressed_size;
219
19.0k
  if (algorithm.decompress_fn(compressed_buffer.get(), compressed_size,
220
19.0k
                              decompressed_buffer.get(), &decompressed_size,
221
19.0k
                              nullptr) != LZO_E_OK) {
222
0
    abort();
223
0
  }
224
225
19.0k
  if (decompressed_size != input_buffer.size()) {
226
0
    fprintf(stderr, "Decompressed size %zu does not match original size %zu.\n",
227
0
            decompressed_size, input_buffer.size());
228
0
    abort();
229
19.0k
  } else if (memcmp(input_buffer.data(), decompressed_buffer.get(),
230
19.0k
                    input_buffer.size()) != 0) {
231
0
    fprintf(stderr,
232
0
            "Decompressed buffer does not match original buffer of size %zu.\n",
233
0
            input_buffer.size());
234
0
    abort();
235
0
  }
236
19.0k
}
237
238
}  // namespace
239
240
19.0k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
241
19.0k
  static bool initialized __attribute__((unused)) = []() {
242
1
    if (lzo_init() != LZO_E_OK) {
243
0
      abort();
244
0
    }
245
1
    return true;
246
1
  }();
247
248
19.0k
  FuzzedDataProvider data_provider(data, size);
249
19.0k
  const auto& algorithms = GetLzoAlgorithms();
250
19.0k
  const auto first_level_index =
251
19.0k
      data_provider.ConsumeIntegralInRange<size_t>(0, algorithms.size() - 1);
252
19.0k
  const auto& algorithm_group = algorithms[first_level_index];
253
19.0k
  const auto second_level_index = data_provider.ConsumeIntegralInRange<size_t>(
254
19.0k
      0, algorithm_group.size() - 1);
255
19.0k
  const std::vector<uint8_t> input_buffer =
256
19.0k
      data_provider.ConsumeRemainingBytes<uint8_t>();
257
19.0k
  FuzzLzoAlgorithm(algorithm_group[second_level_index], input_buffer);
258
19.0k
  return 0;
259
19.0k
}