Coverage Report

Created: 2024-05-21 06:11

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