mirror of https://github.com/google/oss-fuzz.git
Implement a fuzz target for all the compression algorithms in LZO. The fuzzer dynamically switches between algorithms using the FuzzedDataProvider adapter. (#2966)
This commit is contained in:
parent
0ea36d93e3
commit
20360201ad
|
@ -19,5 +19,5 @@ MAINTAINER info@oberhumer.com
|
|||
RUN apt-get update && apt-get install -y make autoconf automake libtool wget
|
||||
RUN wget -O lzo.tar.gz \
|
||||
http://www.oberhumer.com/opensource/lzo/download/lzo-2.10.tar.gz
|
||||
COPY *.c *.options build.sh $SRC/
|
||||
COPY *.c *.cc *.options build.sh $SRC/
|
||||
COPY lzo_decompress_target_seeds $SRC/lzo_decompress_target_seeds
|
||||
|
|
|
@ -0,0 +1,255 @@
|
|||
// Copyright 2019 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <fuzzer/FuzzedDataProvider.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "lzo1.h"
|
||||
#include "lzo1a.h"
|
||||
#include "lzo1b.h"
|
||||
#include "lzo1c.h"
|
||||
#include "lzo1f.h"
|
||||
#include "lzo1x.h"
|
||||
#include "lzo1y.h"
|
||||
#include "lzo1z.h"
|
||||
#include "lzo2a.h"
|
||||
#include "lzoconf.h"
|
||||
|
||||
namespace {
|
||||
|
||||
struct LzoAlgorithm {
|
||||
enum class Category { LZO1, LZO2 };
|
||||
enum class Type {
|
||||
LZO1,
|
||||
LZO1A,
|
||||
LZO1B,
|
||||
LZO1C,
|
||||
LZO1F,
|
||||
LZO1X,
|
||||
LZO1Y,
|
||||
LZO1Z,
|
||||
LZO2A
|
||||
};
|
||||
|
||||
constexpr LzoAlgorithm(Category category, Type type, int compression_level,
|
||||
int memory_level, lzo_compress_t compress_fn,
|
||||
lzo_decompress_t decompress_fn,
|
||||
size_t working_memory_size)
|
||||
: category(category),
|
||||
type(type),
|
||||
compression_level(compression_level),
|
||||
memory_level(memory_level),
|
||||
compress_fn(compress_fn),
|
||||
decompress_fn(decompress_fn),
|
||||
working_memory_size(working_memory_size) {}
|
||||
|
||||
size_t GetMaxCompressedSize(size_t size) const {
|
||||
// Formula taken from the LZO FAQ.
|
||||
switch (category) {
|
||||
case Category::LZO1:
|
||||
return size + (size / 16) + 64 + 3;
|
||||
case Category::LZO2:
|
||||
return size + (size / 8) + 128 + 3;
|
||||
}
|
||||
}
|
||||
|
||||
Category category;
|
||||
Type type;
|
||||
int compression_level;
|
||||
int memory_level;
|
||||
|
||||
lzo_compress_t compress_fn;
|
||||
lzo_decompress_t decompress_fn;
|
||||
size_t working_memory_size;
|
||||
};
|
||||
|
||||
static const std::vector<std::vector<LzoAlgorithm>>& GetLzoAlgorithms() {
|
||||
static auto* algorithms = new std::vector<std::vector<LzoAlgorithm>>{
|
||||
{
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1,
|
||||
0, 0, lzo1_compress, lzo1_decompress, LZO1_MEM_COMPRESS),
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1,
|
||||
99, 0, lzo1_99_compress, lzo1_decompress,
|
||||
LZO1_99_MEM_COMPRESS),
|
||||
},
|
||||
{
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1A,
|
||||
0, 0, lzo1a_compress, lzo1a_decompress,
|
||||
LZO1A_MEM_COMPRESS),
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1A,
|
||||
99, 0, lzo1a_99_compress, lzo1a_decompress,
|
||||
LZO1A_99_MEM_COMPRESS),
|
||||
},
|
||||
{
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
|
||||
1, 0, lzo1b_1_compress, lzo1b_decompress,
|
||||
LZO1B_MEM_COMPRESS),
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
|
||||
2, 0, lzo1b_2_compress, lzo1b_decompress,
|
||||
LZO1B_MEM_COMPRESS),
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
|
||||
3, 0, lzo1b_3_compress, lzo1b_decompress,
|
||||
LZO1B_MEM_COMPRESS),
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
|
||||
4, 0, lzo1b_4_compress, lzo1b_decompress,
|
||||
LZO1B_MEM_COMPRESS),
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
|
||||
5, 0, lzo1b_5_compress, lzo1b_decompress,
|
||||
LZO1B_MEM_COMPRESS),
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
|
||||
6, 0, lzo1b_6_compress, lzo1b_decompress,
|
||||
LZO1B_MEM_COMPRESS),
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
|
||||
7, 0, lzo1b_7_compress, lzo1b_decompress,
|
||||
LZO1B_MEM_COMPRESS),
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
|
||||
8, 0, lzo1b_8_compress, lzo1b_decompress,
|
||||
LZO1B_MEM_COMPRESS),
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
|
||||
9, 0, lzo1b_9_compress, lzo1b_decompress,
|
||||
LZO1B_MEM_COMPRESS),
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
|
||||
99, 0, lzo1b_99_compress, lzo1b_decompress,
|
||||
LZO1B_99_MEM_COMPRESS),
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1B,
|
||||
999, 0, lzo1b_999_compress, lzo1b_decompress,
|
||||
LZO1B_999_MEM_COMPRESS),
|
||||
},
|
||||
{
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1C,
|
||||
1, 0, lzo1c_1_compress, lzo1c_decompress,
|
||||
LZO1C_MEM_COMPRESS),
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1C,
|
||||
5, 0, lzo1c_5_compress, lzo1c_decompress,
|
||||
LZO1C_MEM_COMPRESS),
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1C,
|
||||
9, 0, lzo1c_9_compress, lzo1c_decompress,
|
||||
LZO1C_MEM_COMPRESS),
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1C,
|
||||
99, 0, lzo1c_99_compress, lzo1c_decompress,
|
||||
LZO1C_99_MEM_COMPRESS),
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1C,
|
||||
999, 0, lzo1c_999_compress, lzo1c_decompress,
|
||||
LZO1C_999_MEM_COMPRESS),
|
||||
},
|
||||
{
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1F,
|
||||
1, 0, lzo1f_1_compress, lzo1f_decompress,
|
||||
LZO1F_MEM_COMPRESS),
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1F,
|
||||
999, 0, lzo1f_999_compress, lzo1f_decompress,
|
||||
LZO1F_999_MEM_COMPRESS),
|
||||
},
|
||||
{
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1X,
|
||||
1, 0, lzo1x_1_compress, lzo1x_decompress,
|
||||
LZO1X_1_MEM_COMPRESS),
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1X,
|
||||
1, 11, lzo1x_1_11_compress, lzo1x_decompress,
|
||||
LZO1X_1_11_MEM_COMPRESS),
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1X,
|
||||
1, 12, lzo1x_1_12_compress, lzo1x_decompress,
|
||||
LZO1X_1_12_MEM_COMPRESS),
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1X,
|
||||
1, 15, lzo1x_1_15_compress, lzo1x_decompress,
|
||||
LZO1X_1_15_MEM_COMPRESS),
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1X,
|
||||
999, 0, lzo1x_999_compress, lzo1x_decompress,
|
||||
LZO1X_999_MEM_COMPRESS),
|
||||
},
|
||||
{
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1Y,
|
||||
1, 0, lzo1y_1_compress, lzo1y_decompress,
|
||||
LZO1Y_MEM_COMPRESS),
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1Y,
|
||||
999, 0, lzo1y_999_compress, lzo1y_decompress,
|
||||
LZO1Y_999_MEM_COMPRESS),
|
||||
},
|
||||
{
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO1, LzoAlgorithm::Type::LZO1Z,
|
||||
999, 0, lzo1z_999_compress, lzo1z_decompress,
|
||||
LZO1Z_999_MEM_COMPRESS),
|
||||
},
|
||||
{
|
||||
LzoAlgorithm(LzoAlgorithm::Category::LZO2, LzoAlgorithm::Type::LZO2A,
|
||||
999, 0, lzo2a_999_compress, lzo2a_decompress,
|
||||
LZO2A_999_MEM_COMPRESS),
|
||||
},
|
||||
};
|
||||
return *algorithms;
|
||||
}
|
||||
|
||||
void FuzzLzoAlgorithm(const LzoAlgorithm& algorithm,
|
||||
const std::vector<uint8_t>& input_buffer) {
|
||||
std::unique_ptr<uint8_t[]> working_buffer(
|
||||
new uint8_t[algorithm.working_memory_size]);
|
||||
std::unique_ptr<uint8_t[]> compressed_buffer(
|
||||
new uint8_t[algorithm.GetMaxCompressedSize(input_buffer.size())]);
|
||||
|
||||
lzo_uint compressed_size;
|
||||
if (algorithm.compress_fn(input_buffer.data(), input_buffer.size(),
|
||||
compressed_buffer.get(), &compressed_size,
|
||||
working_buffer.get()) != LZO_E_OK) {
|
||||
abort();
|
||||
}
|
||||
|
||||
std::unique_ptr<uint8_t[]> decompressed_buffer(
|
||||
new uint8_t[input_buffer.size()]);
|
||||
lzo_uint decompressed_size;
|
||||
if (algorithm.decompress_fn(compressed_buffer.get(), compressed_size,
|
||||
decompressed_buffer.get(), &decompressed_size,
|
||||
nullptr) != LZO_E_OK) {
|
||||
abort();
|
||||
}
|
||||
|
||||
if (decompressed_size != input_buffer.size()) {
|
||||
fprintf(stderr, "Decompressed size %zu does not match original size %zu.\n",
|
||||
decompressed_size, input_buffer.size());
|
||||
abort();
|
||||
} else if (memcmp(input_buffer.data(), decompressed_buffer.get(),
|
||||
input_buffer.size()) != 0) {
|
||||
fprintf(stderr,
|
||||
"Decompressed buffer does not match original buffer of size %zu.\n",
|
||||
input_buffer.size());
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
static bool initialized __attribute__((unused)) = []() {
|
||||
if (lzo_init() != LZO_E_OK) {
|
||||
abort();
|
||||
}
|
||||
return true;
|
||||
}();
|
||||
|
||||
FuzzedDataProvider data_provider(data, size);
|
||||
const auto& algorithms = GetLzoAlgorithms();
|
||||
const auto first_level_index =
|
||||
data_provider.ConsumeIntegralInRange<size_t>(0, algorithms.size() - 1);
|
||||
const auto& algorithm_group = algorithms[first_level_index];
|
||||
const auto second_level_index = data_provider.ConsumeIntegralInRange<size_t>(
|
||||
0, algorithm_group.size() - 1);
|
||||
const std::vector<uint8_t> input_buffer =
|
||||
data_provider.ConsumeRemainingBytes<uint8_t>();
|
||||
FuzzLzoAlgorithm(algorithm_group[second_level_index], input_buffer);
|
||||
return 0;
|
||||
}
|
|
@ -30,6 +30,10 @@ do
|
|||
-o $OUT/${name} $LIB_FUZZING_ENGINE src/.libs/liblzo2.a
|
||||
done
|
||||
|
||||
$CXX $CXXFLAGS -std=c++11 -I include -I minilzo -I include/lzo \
|
||||
$SRC/all_lzo_compress.cc \
|
||||
-o $OUT/all_lzo_compress $LIB_FUZZING_ENGINE src/.libs/liblzo2.a
|
||||
|
||||
# copy fuzzer options
|
||||
cp $SRC/*.options $OUT/
|
||||
zip -j $OUT/lzo_decompress_target_seed_corpus.zip $SRC/lzo_decompress_target_seeds/*
|
||||
|
|
Loading…
Reference in New Issue