Coverage Report

Created: 2025-07-11 07:01

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