#ifndef WEBP_TESTS_FUZZER_FUZZ_UTILS_H_
#define WEBP_TESTS_FUZZER_FUZZ_UTILS_H_
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include "./img_alpha.h"
#include "./img_grid.h"
#include "./img_peak.h"
#include "src/dsp/cpu.h"
#include "src/webp/encode.h"
#include "fuzztest/fuzztest.h"
namespace fuzz_utils {
#if defined(__SANITIZE_ADDRESS__)
static const size_t kFuzzPxLimit = 1024 * 1024 / 10;
#elif !defined(__has_feature)
static const size_t kFuzzPxLimit = 1024 * 1024;
#elif __has_feature(address_sanitizer) || __has_feature(memory_sanitizer)
static const size_t kFuzzPxLimit = 1024 * 1024 / 18;
#else
static const size_t kFuzzPxLimit = 1024 * 1024;
#endif
static const int kFuzzFrameLimit = 3;
static WEBP_INLINE uint8_t FuzzHash(const uint8_t* const data, size_t size) {
uint8_t value = 0;
size_t incr = size / 128;
if (!incr) incr = 1;
for (size_t i = 0; i < size; i += incr) value += data[i];
return value;
}
#ifdef __cplusplus
extern "C" VP8CPUInfo VP8GetCPUInfo;
#else
extern VP8CPUInfo VP8GetCPUInfo;
#endif
constexpr const uint8_t* kImagesData[] = {kImgAlphaData, kImgGridData,
kImgPeakData};
constexpr size_t kNumSourceImages =
sizeof(kImagesData) / sizeof(kImagesData[0]);
WebPPicture GetSourcePicture(int image_index, bool use_argb);
static inline auto ArbitraryWebPConfig() {
return fuzztest::Map(
[](int lossless, int quality, int method, int image_hint, int segments,
int sns_strength, int filter_strength, int filter_sharpness,
int filter_type, int autofilter, int alpha_compression,
int alpha_filtering, int alpha_quality, int pass, int preprocessing,
int partitions, int partition_limit, int emulate_jpeg_size,
int thread_level, int low_memory, int near_lossless, int exact,
int use_delta_palette, int use_sharp_yuv) -> WebPConfig {
WebPConfig config;
if (!WebPConfigInit(&config)) abort();
config.lossless = lossless;
config.quality = quality;
config.method = method;
config.image_hint = (WebPImageHint)image_hint;
config.segments = segments;
config.sns_strength = sns_strength;
config.filter_strength = filter_strength;
config.filter_sharpness = filter_sharpness;
config.filter_type = filter_type;
config.autofilter = autofilter;
config.alpha_compression = alpha_compression;
config.alpha_filtering = alpha_filtering;
config.alpha_quality = alpha_quality;
config.pass = pass;
config.show_compressed = 1;
config.preprocessing = preprocessing;
config.partitions = partitions;
config.partition_limit = 10 * partition_limit;
config.emulate_jpeg_size = emulate_jpeg_size;
config.thread_level = thread_level;
config.low_memory = low_memory;
config.near_lossless = 20 * near_lossless;
config.exact = exact;
config.use_delta_palette = use_delta_palette;
config.use_sharp_yuv = use_sharp_yuv;
if (!WebPValidateConfig(&config)) abort();
return config;
},
fuzztest::InRange<int>(0, 1),
fuzztest::InRange<int>(0, 100),
fuzztest::InRange<int>(0, 6),
fuzztest::InRange<int>(0, WEBP_HINT_LAST - 1),
fuzztest::InRange<int>(1, 4),
fuzztest::InRange<int>(0, 100),
fuzztest::InRange<int>(0, 100),
fuzztest::InRange<int>(0, 7),
fuzztest::InRange<int>(0, 1),
fuzztest::InRange<int>(0, 1),
fuzztest::InRange<int>(0, 1),
fuzztest::InRange<int>(0, 2),
fuzztest::InRange<int>(0, 100),
fuzztest::InRange<int>(1, 10),
fuzztest::InRange<int>(0, 2),
fuzztest::InRange<int>(0, 3),
fuzztest::InRange<int>(0, 10),
fuzztest::InRange<int>(0, 1),
fuzztest::InRange<int>(0, 1),
fuzztest::InRange<int>(0, 1),
fuzztest::InRange<int>(0, 5),
fuzztest::InRange<int>(0, 1),
fuzztest::InRange<int>(0, 1),
fuzztest::InRange<int>(0, 1));
}
struct CropOrScaleParams {
bool alter_input;
bool crop_or_scale;
int width_ratio;
int height_ratio;
int left_ratio;
int top_ratio;
};
static inline auto ArbitraryCropOrScaleParams() {
return fuzztest::Map(
[](const std::optional<std::pair<int, int>>& width_height_ratio,
const std::optional<std::pair<int, int>>& left_top_ratio)
-> CropOrScaleParams {
CropOrScaleParams params;
params.alter_input = width_height_ratio.has_value();
if (params.alter_input) {
params.width_ratio = width_height_ratio->first;
params.height_ratio = width_height_ratio->second;
params.crop_or_scale = left_top_ratio.has_value();
if (params.crop_or_scale) {
params.left_ratio = left_top_ratio->first;
params.top_ratio = left_top_ratio->second;
}
}
return params;
},
fuzztest::OptionalOf(
fuzztest::PairOf(fuzztest::InRange(1, 8), fuzztest::InRange(1, 8))),
fuzztest::OptionalOf(
fuzztest::PairOf(fuzztest::InRange(1, 8), fuzztest::InRange(1, 8))));
}
int CropOrScale(WebPPicture* pic, const CropOrScaleParams& params);
static constexpr uint32_t kMaxOptimizationIndex = 4;
void SetOptimization(VP8CPUInfo default_VP8GetCPUInfo, uint32_t index);
static constexpr size_t kMaxWebPFileSize = (1ull << 32) - 2;
std::vector<std::string> GetDictionaryFromFiles(
const std::vector<std::string_view>& file_paths);
bool IsImageTooBig(const uint8_t* data, size_t size);
}
#endif