Initial release

This commit is contained in:
civ
2026-08-16 18:27:57 +07:00
commit 8ff9ca0fc0
3800 changed files with 848933 additions and 0 deletions
+75
View File
@@ -0,0 +1,75 @@
# Copyright (c) 2024 Google LLC
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
# Adds a fuzztest from file TEST_NAME.cc located in the gtest folder. Extra
# arguments are considered as extra source files.
if(CMAKE_VERSION VERSION_LESS "3.19.0")
return()
endif()
macro(add_webp_fuzztest TEST_NAME)
add_executable(${TEST_NAME} ${TEST_NAME}.cc)
# FuzzTest bundles GoogleTest so no need to link to gtest libraries.
target_link_libraries(${TEST_NAME} PRIVATE fuzz_utils webp ${ARGN})
target_include_directories(${TEST_NAME} PRIVATE ${CMAKE_BINARY_DIR}/src)
link_fuzztest(${TEST_NAME})
add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME})
set_property(
TEST ${TEST_NAME}
PROPERTY ENVIRONMENT "TEST_DATA_DIRS=${CMAKE_CURRENT_SOURCE_DIR}/data/")
endmacro()
enable_language(CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
include(FetchContent)
set(FETCHCONTENT_QUIET FALSE)
set(fuzztest_SOURCE_DIR ${CMAKE_BINARY_DIR}/_deps/fuzztest-src)
FetchContent_Declare(
fuzztest
GIT_REPOSITORY https://github.com/google/fuzztest.git
GIT_TAG 078ea0871cc96d3a69bad406577f176a4fa14ae9
GIT_PROGRESS TRUE
PATCH_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/patch.sh)
FetchContent_MakeAvailable(fuzztest)
fuzztest_setup_fuzzing_flags()
add_library(fuzz_utils fuzz_utils.h fuzz_utils.cc img_alpha.h img_grid.h
img_peak.h)
target_link_libraries(fuzz_utils PUBLIC webpdecoder)
target_include_directories(fuzz_utils PUBLIC ${CMAKE_SOURCE_DIR}
${CMAKE_BINARY_DIR})
link_fuzztest(fuzz_utils)
add_webp_fuzztest(advanced_api_fuzzer webpdecode webpdspdecode webputilsdecode)
add_webp_fuzztest(dec_fuzzer)
add_webp_fuzztest(enc_dec_fuzzer webpdecode webpdspdecode webputilsdecode)
add_webp_fuzztest(enc_fuzzer imagedec)
add_webp_fuzztest(huffman_fuzzer webpdecode webpdspdecode webputilsdecode)
add_webp_fuzztest(imageio_fuzzer imagedec)
add_webp_fuzztest(simple_api_fuzzer)
if (WEBP_BUILD_ANIM_UTILS)
add_webp_fuzztest(anim_util_fuzzer anim_util imageioutil webpdemux)
endif()
if(WEBP_BUILD_LIBWEBPMUX)
add_webp_fuzztest(animation_api_fuzzer webpdemux)
add_webp_fuzztest(animdecoder_fuzzer imageioutil webpdemux)
add_webp_fuzztest(animencoder_fuzzer libwebpmux)
add_webp_fuzztest(mux_demux_api_fuzzer libwebpmux webpdemux)
endif()
if(WEBP_BUILD_WEBPINFO)
add_webp_fuzztest(webp_info_fuzzer imageioutil)
endif()
+164
View File
@@ -0,0 +1,164 @@
// Copyright 2018 Google Inc.
//
// 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 <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <string_view>
#include "./fuzz_utils.h"
#include "src/dec/webpi_dec.h"
#include "src/utils/rescaler_utils.h"
#include "webp/decode.h"
namespace {
void AdvancedApiTest(std::string_view blob, uint8_t factor_u8, int colorspace,
bool incremental,
const fuzz_utils::WebPDecoderOptionsCpp& decoder_options) {
WebPDecoderConfig config;
if (!WebPInitDecoderConfig(&config)) return;
const uint8_t* const data = reinterpret_cast<const uint8_t*>(blob.data());
const size_t size = blob.size();
if (WebPGetFeatures(data, size, &config.input) != VP8_STATUS_OK) return;
if ((size_t)config.input.width * config.input.height >
fuzz_utils::kFuzzPxLimit) {
return;
}
// Using two independent criteria ensures that all combinations of options
// can reach each path at the decoding stage, with meaningful differences.
const uint8_t value = fuzz_utils::FuzzHash(data, size);
const float factor = factor_u8 / 255.f; // 0-1
std::memcpy(&config.options, &decoder_options, sizeof(decoder_options));
if (config.options.use_cropping) {
config.options.crop_width = (int)(config.input.width * (1 - factor));
config.options.crop_height = (int)(config.input.height * (1 - factor));
config.options.crop_left = config.input.width - config.options.crop_width;
config.options.crop_top = config.input.height - config.options.crop_height;
}
if (config.options.use_scaling) {
config.options.scaled_width = (int)(config.input.width * factor * 2);
config.options.scaled_height = (int)(config.input.height * factor * 2);
}
config.output.colorspace = static_cast<WEBP_CSP_MODE>(colorspace);
for (int i = 0; i < 2; ++i) {
if (i == 1) {
// Use the bitstream data to generate extreme ranges for the options. An
// alternative approach would be to use a custom corpus containing webp
// files prepended with sizeof(config.options) zeroes to allow the fuzzer
// to modify these independently.
const int data_offset = 50;
if (data_offset + sizeof(config.options) >= size) break;
memcpy(&config.options, data + data_offset, sizeof(config.options));
// Skip easily avoidable out-of-memory fuzzing errors.
if (config.options.use_scaling) {
int input_width = config.input.width;
int input_height = config.input.height;
if (config.options.use_cropping) {
const int cw = config.options.crop_width;
const int ch = config.options.crop_height;
const int x = config.options.crop_left & ~1;
const int y = config.options.crop_top & ~1;
if (WebPCheckCropDimensions(input_width, input_height, x, y, cw,
ch)) {
input_width = cw;
input_height = ch;
}
}
int scaled_width = config.options.scaled_width;
int scaled_height = config.options.scaled_height;
if (WebPRescalerGetScaledDimensions(input_width, input_height,
&scaled_width, &scaled_height)) {
size_t fuzz_px_limit = fuzz_utils::kFuzzPxLimit;
if (scaled_width != config.input.width ||
scaled_height != config.input.height) {
// Using the WebPRescalerImport internally can significantly slow
// down the execution. Avoid timeouts due to that.
fuzz_px_limit /= 2;
}
// A big output canvas can lead to out-of-memory and timeout issues,
// but a big internal working buffer can too. Also, rescaling from a
// very wide input image to a very tall canvas can be as slow as
// decoding a huge number of pixels. Avoid timeouts due to these.
const uint64_t max_num_operations =
(uint64_t)std::max(scaled_width, config.input.width) *
std::max(scaled_height, config.input.height);
if (max_num_operations > fuzz_px_limit) {
break;
}
}
}
}
if (incremental) {
// Decodes incrementally in chunks of increasing size.
WebPIDecoder* idec = WebPIDecode(NULL, 0, &config);
if (!idec) return;
VP8StatusCode status;
if (size & 8) {
size_t available_size = value + 1;
while (1) {
if (available_size > size) available_size = size;
status = WebPIUpdate(idec, data, available_size);
if (status != VP8_STATUS_SUSPENDED || available_size == size) break;
available_size *= 2;
}
} else {
// WebPIAppend expects new data and its size with each call.
// Implemented here by simply advancing the pointer into data.
const uint8_t* new_data = data;
size_t new_size = value + 1;
while (1) {
if (new_data + new_size > data + size) {
new_size = data + size - new_data;
}
status = WebPIAppend(idec, new_data, new_size);
if (status != VP8_STATUS_SUSPENDED || new_size == 0) break;
new_data += new_size;
new_size *= 2;
}
}
WebPIDelete(idec);
} else {
(void)WebPDecode(data, size, &config);
}
WebPFreeDecBuffer(&config.output);
}
}
} // namespace
FUZZ_TEST(AdvancedApi, AdvancedApiTest)
.WithDomains(fuzztest::String().WithMaxSize(fuzz_utils::kMaxWebPFileSize +
1),
/*factor_u8=*/fuzztest::Arbitrary<uint8_t>(),
#if defined(WEBP_REDUCE_CSP)
fuzztest::ElementOf<int>({static_cast<int>(MODE_RGBA),
static_cast<int>(MODE_BGRA),
static_cast<int>(MODE_rgbA),
static_cast<int>(MODE_bgrA)}),
#else
fuzztest::InRange<int>(0, static_cast<int>(MODE_LAST) - 1),
#endif
/*incremental=*/fuzztest::Arbitrary<bool>(),
fuzz_utils::ArbitraryValidWebPDecoderOptions());
+49
View File
@@ -0,0 +1,49 @@
// Copyright 2026 Google Inc.
//
// 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 <cstdint>
#include <cstdio>
#include <cstdlib>
#include <string_view>
#include "./fuzz_utils.h"
#include "./nalloc.h"
#include "examples/anim_util.h"
namespace {
void ReadAnimatedImageTest(std::string_view blob) {
const uint8_t* const data = reinterpret_cast<const uint8_t*>(blob.data());
const size_t size = blob.size();
if (fuzz_utils::IsImageTooBig(data, size)) return;
nalloc_init(nullptr);
nalloc_start(data, size);
AnimatedImage image;
if (ReadAnimatedImageFromMemory("random_file", data, size, &image,
/*dump_frames=*/0, /*dump_folder=*/nullptr)) {
ClearAnimatedImage(&image);
}
nalloc_end();
}
} // namespace
FUZZ_TEST(ReadAnimatedImage, ReadAnimatedImageTest)
.WithDomains(fuzztest::String().WithMaxSize(fuzz_utils::kMaxWebPFileSize +
1));
+90
View File
@@ -0,0 +1,90 @@
// Copyright 2018 Google Inc.
//
// 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 <cstddef>
#include <cstdint>
#include <string_view>
#include "./fuzz_utils.h"
#include "webp/decode.h"
#include "webp/demux.h"
#include "webp/mux_types.h"
namespace {
void AnimationApiTest(std::string_view blob, bool use_threads,
WEBP_CSP_MODE color_mode) {
const size_t size = blob.size();
WebPData webp_data;
WebPDataInit(&webp_data);
webp_data.size = size;
webp_data.bytes = reinterpret_cast<const uint8_t*>(blob.data());
// WebPAnimDecoderNew uses WebPDemux internally to calloc canvas size.
WebPDemuxer* const demux = WebPDemux(&webp_data);
if (!demux) return;
const uint32_t cw = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH);
const uint32_t ch = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT);
if ((size_t)cw * ch > fuzz_utils::kFuzzPxLimit) {
WebPDemuxDelete(demux);
return;
}
// In addition to canvas size, check each frame separately.
WebPIterator iter;
for (int i = 0; i < fuzz_utils::kFuzzFrameLimit; i++) {
if (!WebPDemuxGetFrame(demux, i + 1, &iter)) break;
int w, h;
if (WebPGetInfo(iter.fragment.bytes, iter.fragment.size, &w, &h)) {
if ((size_t)w * h >
fuzz_utils::kFuzzPxLimit) { // image size of the frame payload
WebPDemuxReleaseIterator(&iter);
WebPDemuxDelete(demux);
return;
}
}
}
WebPDemuxReleaseIterator(&iter);
WebPDemuxDelete(demux);
WebPAnimDecoderOptions dec_options;
if (!WebPAnimDecoderOptionsInit(&dec_options)) return;
dec_options.use_threads = use_threads;
dec_options.color_mode = color_mode;
WebPAnimDecoder* dec = WebPAnimDecoderNew(&webp_data, &dec_options);
if (!dec) return;
for (int i = 0; i < fuzz_utils::kFuzzFrameLimit; i++) {
uint8_t* buf;
int timestamp;
if (!WebPAnimDecoderGetNext(dec, &buf, &timestamp)) break;
}
WebPAnimDecoderDelete(dec);
}
} // namespace
FUZZ_TEST(AnimationApi, AnimationApiTest)
.WithDomains(fuzztest::String().WithMaxSize(fuzz_utils::kMaxWebPFileSize +
1),
/*use_threads=*/fuzztest::Arbitrary<bool>(),
// Animations only support 4 (out of 12) modes.
fuzztest::ElementOf<WEBP_CSP_MODE>({MODE_RGBA, MODE_BGRA,
MODE_rgbA, MODE_bgrA}));
+81
View File
@@ -0,0 +1,81 @@
// Copyright 2020 Google Inc.
//
// 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 <cstddef>
#include <cstdint>
#include <string_view>
#include "./fuzz_utils.h"
#include "./nalloc.h"
#include "imageio/imageio_util.h"
#include "webp/decode.h"
#include "webp/demux.h"
#include "webp/mux_types.h"
namespace {
void AnimDecoderTest(std::string_view blob) {
const uint8_t* const data = reinterpret_cast<const uint8_t*>(blob.data());
const size_t size = blob.size();
nalloc_init(nullptr);
nalloc_start(data, size);
// WebPAnimDecoderGetInfo() is too late to check the canvas size as
// WebPAnimDecoderNew() will handle the allocations.
const size_t kMaxNumBytes = 2684354560; // RSS (resident set size) limit.
const size_t kMaxNumPixels = kMaxNumBytes / 4; // At most ARGB.
const size_t kMaxNumPixelsSafe = kMaxNumPixels / 2; // Allow one buffer copy.
WebPBitstreamFeatures features;
if (WebPGetFeatures(data, size, &features) == VP8_STATUS_OK) {
if (!ImgIoUtilCheckSizeArgumentsOverflow(features.width * 4,
features.height) ||
static_cast<size_t>(features.width) * features.height >
kMaxNumPixelsSafe) {
nalloc_end();
return;
}
}
// decode everything as an animation
WebPData webp_data = {data, size};
WebPAnimDecoder* const dec = WebPAnimDecoderNew(&webp_data, nullptr);
if (dec == nullptr) {
nalloc_end();
return;
}
WebPAnimInfo info;
if (!WebPAnimDecoderGetInfo(dec, &info)) goto End;
if (!ImgIoUtilCheckSizeArgumentsOverflow(info.canvas_width * 4,
info.canvas_height)) {
goto End;
}
while (WebPAnimDecoderHasMoreFrames(dec)) {
uint8_t* buf;
int timestamp;
if (!WebPAnimDecoderGetNext(dec, &buf, &timestamp)) break;
}
End:
WebPAnimDecoderDelete(dec);
nalloc_end();
}
} // namespace
FUZZ_TEST(AnimDecoder, AnimDecoderTest)
.WithDomains(fuzztest::String().WithMaxSize(fuzz_utils::kMaxWebPFileSize +
1));
+210
View File
@@ -0,0 +1,210 @@
// Copyright 2018 Google Inc.
//
// 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 <cstdint>
#include <cstdio>
#include <cstdlib>
#include <utility>
#include <vector>
#include "./fuzz_utils.h"
#include "src/dsp/cpu.h"
#include "webp/encode.h"
#include "webp/mux.h"
#include "webp/mux_types.h"
namespace {
const VP8CPUInfo default_VP8GetCPUInfo = fuzz_utils::VP8GetCPUInfo;
struct FrameConfig {
int use_argb;
int timestamp;
WebPConfig webp_config;
fuzz_utils::CropOrScaleParams crop_or_scale_params;
fuzz_utils::WebPPictureCpp pic_cpp;
};
auto ArbitraryKMinKMax() {
return fuzztest::FlatMap(
[](int kmax) {
const int min_kmin = (kmax > 1) ? (kmax / 2) : 0;
const int max_kmin = (kmax > 1) ? (kmax - 1) : 0;
return fuzztest::PairOf(fuzztest::InRange(min_kmin, max_kmin),
fuzztest::Just(kmax));
},
fuzztest::InRange(0, 15));
}
int AddFrame(WebPAnimEncoder** const enc,
const WebPAnimEncoderOptions& anim_config, int* const width,
int* const height, int timestamp_ms, FrameConfig& frame_config,
uint32_t* const bit_pos) {
if (enc == nullptr || width == nullptr || height == nullptr) {
fprintf(stderr, "NULL parameters.\n");
if (enc != nullptr) WebPAnimEncoderDelete(*enc);
std::abort();
}
// Init the source picture.
WebPPicture& pic = frame_config.pic_cpp.ref();
// Crop and scale.
if (*enc == nullptr) { // First frame will set canvas width and height.
if (!fuzz_utils::CropOrScale(&pic, frame_config.crop_or_scale_params)) {
const WebPEncodingError error_code = pic.error_code;
if (error_code == VP8_ENC_ERROR_OUT_OF_MEMORY) return 0;
fprintf(stderr, "ExtractAndCropOrScale failed. Error code: %d\n",
error_code);
std::abort();
}
} else { // Other frames will be resized to the first frame's dimensions.
if (!WebPPictureRescale(&pic, *width, *height)) {
const WebPEncodingError error_code = pic.error_code;
WebPAnimEncoderDelete(*enc);
if (error_code == VP8_ENC_ERROR_OUT_OF_MEMORY) return 0;
fprintf(stderr,
"WebPPictureRescale failed. Size: %d,%d. Error code: %d\n",
*width, *height, error_code);
std::abort();
}
}
// Create encoder if it doesn't exist.
if (*enc == nullptr) {
*width = pic.width;
*height = pic.height;
*enc = WebPAnimEncoderNew(*width, *height, &anim_config);
if (*enc == nullptr) {
return 0;
}
}
// Create frame encoding config.
WebPConfig config = frame_config.webp_config;
// Skip slow settings on big images, it's likely to timeout.
if (pic.width * pic.height > 32 * 32) {
config.method = (config.method > 4) ? 4 : config.method;
config.quality = (config.quality > 99.0f) ? 99.0f : config.quality;
config.alpha_quality =
(config.alpha_quality > 99) ? 99 : config.alpha_quality;
}
// Encode.
if (!WebPAnimEncoderAdd(*enc, &pic, timestamp_ms, &config)) {
const WebPEncodingError error_code = pic.error_code;
WebPAnimEncoderDelete(*enc);
// Tolerate failures when running under the nallocfuzz engine as
// WebPAnimEncoderAdd() may fail due to memory allocation errors outside of
// the encoder; in muxer functions that return booleans for instance.
if (error_code == VP8_ENC_ERROR_OUT_OF_MEMORY ||
error_code == VP8_ENC_ERROR_BAD_WRITE ||
getenv("NALLOC_FUZZ_VERSION") != nullptr) {
return 0;
}
fprintf(stderr, "WebPEncode failed. Error code: %d\n", error_code);
std::abort();
}
return 1;
}
void AnimEncoderTest(bool minimize_size, std::pair<int, int> kmin_kmax,
bool allow_mixed, std::vector<FrameConfig> frame_configs,
int optimization_index) {
WebPAnimEncoder* enc = nullptr;
int width = 0, height = 0, timestamp_ms = 0;
uint32_t bit_pos = 0;
fuzz_utils::SetOptimization(default_VP8GetCPUInfo, optimization_index);
// Extract a configuration from the packed bits.
WebPAnimEncoderOptions anim_config;
if (!WebPAnimEncoderOptionsInit(&anim_config)) {
fprintf(stderr, "WebPAnimEncoderOptionsInit failed.\n");
std::abort();
}
anim_config.minimize_size = minimize_size;
anim_config.kmin = kmin_kmax.first;
anim_config.kmax = kmin_kmax.second;
anim_config.allow_mixed = allow_mixed;
anim_config.verbose = 0;
// For each frame.
for (FrameConfig& frame_config : frame_configs) {
if (!AddFrame(&enc, anim_config, &width, &height, timestamp_ms,
frame_config, &bit_pos)) {
return;
}
timestamp_ms += frame_config.timestamp;
}
// Assemble.
if (!WebPAnimEncoderAdd(enc, nullptr, timestamp_ms, nullptr)) {
fprintf(stderr, "Last WebPAnimEncoderAdd failed: %s.\n",
WebPAnimEncoderGetError(enc));
WebPAnimEncoderDelete(enc);
std::abort();
}
WebPData webp_data;
WebPDataInit(&webp_data);
// Tolerate failures when running under the nallocfuzz engine as allocations
// during assembly may fail.
if (!WebPAnimEncoderAssemble(enc, &webp_data) &&
getenv("NALLOC_FUZZ_VERSION") == nullptr) {
fprintf(stderr, "WebPAnimEncoderAssemble failed: %s.\n",
WebPAnimEncoderGetError(enc));
WebPAnimEncoderDelete(enc);
WebPDataClear(&webp_data);
std::abort();
}
WebPAnimEncoderDelete(enc);
WebPDataClear(&webp_data);
}
} // namespace
FUZZ_TEST(AnimIndexEncoder, AnimEncoderTest)
.WithDomains(
/*minimize_size=*/fuzztest::Arbitrary<bool>(), ArbitraryKMinKMax(),
/*allow_mixed=*/fuzztest::Arbitrary<bool>(),
fuzztest::VectorOf(fuzztest::StructOf<FrameConfig>(
fuzztest::InRange<int>(0, 1),
fuzztest::InRange<int>(0, 131073),
fuzz_utils::ArbitraryWebPConfig(),
fuzz_utils::ArbitraryCropOrScaleParams(),
fuzz_utils::ArbitraryWebPPictureFromIndex()))
.WithMinSize(1)
.WithMaxSize(15),
/*optimization_index=*/
fuzztest::InRange<uint32_t>(0, fuzz_utils::kMaxOptimizationIndex));
FUZZ_TEST(AnimArbitraryEncoder, AnimEncoderTest)
.WithDomains(
/*minimize_size=*/fuzztest::Arbitrary<bool>(), ArbitraryKMinKMax(),
/*allow_mixed=*/fuzztest::Arbitrary<bool>(),
fuzztest::VectorOf(fuzztest::StructOf<FrameConfig>(
fuzztest::InRange<int>(0, 1),
fuzztest::InRange<int>(0, 131073),
fuzz_utils::ArbitraryWebPConfig(),
fuzz_utils::ArbitraryCropOrScaleParams(),
fuzz_utils::ArbitraryWebPPicture()))
.WithMinSize(1)
.WithMaxSize(15),
/*optimization_index=*/
fuzztest::InRange<uint32_t>(0, fuzz_utils::kMaxOptimizationIndex));
+58
View File
@@ -0,0 +1,58 @@
// Copyright 2024 Google Inc.
//
// 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 <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string_view>
#include "./nalloc.h"
#include "tests/fuzzer/fuzz_utils.h"
#include "webp/decode.h"
namespace {
void DecodeWebP(std::string_view arbitrary_bytes,
const fuzz_utils::WebPDecoderOptionsCpp& decoder_options) {
WebPDecoderConfig decoder_config;
if (!WebPInitDecoderConfig(&decoder_config)) {
fprintf(stderr, "WebPInitDecoderConfig failed.\n");
std::abort();
}
nalloc_init(nullptr);
nalloc_start(reinterpret_cast<const uint8_t*>(arbitrary_bytes.data()),
arbitrary_bytes.size());
std::memcpy(&decoder_config.options, &decoder_options,
sizeof(decoder_options));
const VP8StatusCode status =
WebPDecode(reinterpret_cast<const uint8_t*>(arbitrary_bytes.data()),
arbitrary_bytes.size(), &decoder_config);
WebPFreeDecBuffer(&decoder_config.output);
// The decoding may fail (because the fuzzed input can be anything) but not
// for these reasons.
if (status == VP8_STATUS_SUSPENDED || status == VP8_STATUS_USER_ABORT) {
std::abort();
}
nalloc_end();
}
FUZZ_TEST(WebPSuite, DecodeWebP)
.WithDomains(fuzztest::String().WithMaxSize(fuzz_utils::kMaxWebPFileSize +
1),
fuzz_utils::ArbitraryValidWebPDecoderOptions());
} // namespace
+263
View File
@@ -0,0 +1,263 @@
// Copyright 2018 Google Inc.
//
// 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 <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <memory>
#include "./fuzz_utils.h"
#include "src/dsp/cpu.h"
#include "src/utils/rescaler_utils.h"
#include "webp/decode.h"
#include "webp/encode.h"
namespace {
const VP8CPUInfo default_VP8GetCPUInfo = fuzz_utils::VP8GetCPUInfo;
void Enc(const fuzz_utils::CropOrScaleParams& crop_or_scale_params,
WebPConfig& config, WebPPicture& pic,
WebPMemoryWriter& memory_writer) {
// Crop and scale.
if (!fuzz_utils::CropOrScale(&pic, crop_or_scale_params)) {
const WebPEncodingError error_code = pic.error_code;
if (error_code == VP8_ENC_ERROR_OUT_OF_MEMORY) return;
fprintf(stderr, "ExtractAndCropOrScale failed. Error code: %d\n",
error_code);
std::abort();
}
// Skip slow settings on big images, it's likely to timeout.
if (pic.width * pic.height > 32 * 32) {
if (config.lossless) {
if (config.quality > 99.0f && config.method >= 5) {
config.quality = 99.0f;
config.method = 5;
}
} else {
if (config.quality > 99.0f && config.method == 6) {
config.quality = 99.0f;
}
}
if (config.alpha_quality == 100 && config.method == 6) {
config.alpha_quality = 99;
}
}
// Encode.
pic.writer = WebPMemoryWrite;
pic.custom_ptr = &memory_writer;
if (!WebPEncode(&config, &pic)) {
const WebPEncodingError error_code = pic.error_code;
if (error_code == VP8_ENC_ERROR_OUT_OF_MEMORY ||
error_code == VP8_ENC_ERROR_BAD_WRITE) {
return;
}
fprintf(stderr, "WebPEncode failed. Error code: %d\n", error_code);
std::abort();
}
}
void EncDecValidTest(bool use_argb, fuzz_utils::WebPPictureCpp pic_cpp,
WebPConfig config, int optimization_index,
const fuzz_utils::CropOrScaleParams& crop_or_scale_params,
int colorspace,
const fuzz_utils::WebPDecoderOptionsCpp& decoder_options) {
fuzz_utils::SetOptimization(default_VP8GetCPUInfo, optimization_index);
// Init the source picture.
WebPPicture& pic = pic_cpp.ref();
WebPMemoryWriter memory_writer;
WebPMemoryWriterInit(&memory_writer);
std::unique_ptr<WebPMemoryWriter, fuzz_utils::UniquePtrDeleter>
memory_writer_owner(&memory_writer);
Enc(crop_or_scale_params, config, pic, memory_writer);
// Try decoding the result.
const uint8_t* const out_data = memory_writer.mem;
const size_t out_size = memory_writer.size;
WebPDecoderConfig dec_config;
std::unique_ptr<WebPDecoderConfig, fuzz_utils::UniquePtrDeleter>
dec_config_owner(&dec_config);
if (!WebPInitDecoderConfig(&dec_config)) {
fprintf(stderr, "WebPInitDecoderConfig failed.\n");
std::abort();
}
dec_config.output.colorspace = MODE_BGRA;
VP8StatusCode status = WebPDecode(out_data, out_size, &dec_config);
if ((status != VP8_STATUS_OK && status != VP8_STATUS_OUT_OF_MEMORY &&
status != VP8_STATUS_USER_ABORT) ||
(status == VP8_STATUS_OK && (dec_config.output.width != pic.width ||
dec_config.output.height != pic.height))) {
fprintf(stderr, "WebPDecode failed. status: %d.\n", status);
std::abort();
}
// Compare the results if exact encoding.
if (status == VP8_STATUS_OK && pic.use_argb && config.lossless &&
config.near_lossless == 100) {
const uint8_t* const rgba = dec_config.output.u.RGBA.rgba;
const int w = dec_config.output.width;
const int h = dec_config.output.height;
const uint32_t* src1 = (const uint32_t*)rgba;
const uint32_t* src2 = pic.argb;
for (int y = 0; y < h; ++y, src1 += w, src2 += pic.argb_stride) {
for (int x = 0; x < w; ++x) {
uint32_t v1 = src1[x], v2 = src2[x];
if (!config.exact) {
if ((v1 & 0xff000000u) == 0 || (v2 & 0xff000000u) == 0) {
// Only keep alpha for comparison of fully transparent area.
v1 &= 0xff000000u;
v2 &= 0xff000000u;
}
}
if (v1 != v2) {
fprintf(stderr, "Lossless compression failed pixel-exactness.\n");
std::abort();
}
}
}
}
// Use given decoding options.
if (static_cast<int64_t>(decoder_options.crop_left) +
decoder_options.crop_width >
static_cast<int64_t>(pic.width) ||
static_cast<int64_t>(decoder_options.crop_top) +
decoder_options.crop_height >
static_cast<int64_t>(pic.height)) {
return;
}
WebPFreeDecBuffer(&dec_config.output);
if (!WebPInitDecoderConfig(&dec_config)) {
fprintf(stderr, "WebPInitDecoderConfig failed.\n");
abort();
}
dec_config.output.colorspace = static_cast<WEBP_CSP_MODE>(colorspace);
std::memcpy(&dec_config.options, &decoder_options, sizeof(decoder_options));
status = WebPDecode(out_data, out_size, &dec_config);
if (status != VP8_STATUS_OK && status != VP8_STATUS_OUT_OF_MEMORY &&
status != VP8_STATUS_USER_ABORT) {
fprintf(stderr, "WebPDecode failed. status: %d.\n", status);
abort();
}
}
////////////////////////////////////////////////////////////////////////////////
void EncDecTest(bool use_argb, fuzz_utils::WebPPictureCpp pic_cpp,
WebPConfig config, int optimization_index,
const fuzz_utils::CropOrScaleParams& crop_or_scale_params,
int colorspace,
const fuzz_utils::WebPDecoderOptionsCpp& decoder_options) {
fuzz_utils::SetOptimization(default_VP8GetCPUInfo, optimization_index);
// Init the source picture.
WebPPicture& pic = pic_cpp.ref();
WebPMemoryWriter memory_writer;
WebPMemoryWriterInit(&memory_writer);
std::unique_ptr<WebPMemoryWriter, fuzz_utils::UniquePtrDeleter>
memory_writer_owner(&memory_writer);
Enc(crop_or_scale_params, config, pic, memory_writer);
// Try decoding the result.
const uint8_t* const out_data = memory_writer.mem;
const size_t out_size = memory_writer.size;
WebPDecoderConfig dec_config;
std::unique_ptr<WebPDecoderConfig, fuzz_utils::UniquePtrDeleter>
dec_config_owner(&dec_config);
if (!WebPInitDecoderConfig(&dec_config)) {
fprintf(stderr, "WebPInitDecoderConfig failed.\n");
abort();
}
if (decoder_options.use_scaling) {
int scaled_width = decoder_options.scaled_width;
int scaled_height = decoder_options.scaled_height;
if (!WebPRescalerGetScaledDimensions(pic.width, pic.height, &scaled_width,
&scaled_height)) {
// Rescaled dimensions do not make sense.
return;
}
if (static_cast<uint64_t>(scaled_width) * scaled_height > 1000u * 1000u) {
// Skip huge scaling.
return;
}
}
dec_config.output.colorspace = static_cast<WEBP_CSP_MODE>(colorspace);
std::memcpy(&dec_config.options, &decoder_options, sizeof(decoder_options));
const VP8StatusCode status = WebPDecode(out_data, out_size, &dec_config);
if (status != VP8_STATUS_OK && status != VP8_STATUS_OUT_OF_MEMORY &&
status != VP8_STATUS_USER_ABORT && status != VP8_STATUS_INVALID_PARAM) {
fprintf(stderr, "WebPDecode failed. status: %d.\n", status);
abort();
}
}
} // namespace
FUZZ_TEST(EncIndexDec, EncDecValidTest)
.WithDomains(/*use_argb=*/fuzztest::Arbitrary<bool>(),
fuzz_utils::ArbitraryWebPPictureFromIndex(),
fuzz_utils::ArbitraryWebPConfig(),
/*optimization_index=*/
fuzztest::InRange<uint32_t>(0,
fuzz_utils::kMaxOptimizationIndex),
fuzz_utils::ArbitraryCropOrScaleParams(),
/*colorspace=*/fuzztest::InRange<int>(0, MODE_LAST - 1),
fuzz_utils::ArbitraryValidWebPDecoderOptions());
FUZZ_TEST(EncArbitraryDec, EncDecValidTest)
.WithDomains(/*use_argb=*/fuzztest::Arbitrary<bool>(),
fuzz_utils::ArbitraryWebPPicture(),
fuzz_utils::ArbitraryWebPConfig(),
/*optimization_index=*/
fuzztest::InRange<uint32_t>(0,
fuzz_utils::kMaxOptimizationIndex),
fuzz_utils::ArbitraryCropOrScaleParams(),
/*colorspace=*/fuzztest::InRange<int>(0, MODE_LAST - 1),
fuzz_utils::ArbitraryValidWebPDecoderOptions());
FUZZ_TEST(EncIndexDec, EncDecTest)
.WithDomains(/*use_argb=*/fuzztest::Arbitrary<bool>(),
fuzz_utils::ArbitraryWebPPictureFromIndex(),
fuzz_utils::ArbitraryWebPConfig(),
/*optimization_index=*/
fuzztest::InRange<uint32_t>(0,
fuzz_utils::kMaxOptimizationIndex),
fuzz_utils::ArbitraryCropOrScaleParams(),
/*colorspace=*/fuzztest::Arbitrary<int>(),
fuzz_utils::ArbitraryWebPDecoderOptions());
FUZZ_TEST(EncArbitraryDec, EncDecTest)
.WithDomains(/*use_argb=*/fuzztest::Arbitrary<bool>(),
fuzz_utils::ArbitraryWebPPicture(),
fuzz_utils::ArbitraryWebPConfig(),
/*optimization_index=*/
fuzztest::InRange<uint32_t>(0,
fuzz_utils::kMaxOptimizationIndex),
fuzz_utils::ArbitraryCropOrScaleParams(),
/*colorspace=*/fuzztest::Arbitrary<int>(),
fuzz_utils::ArbitraryWebPDecoderOptions());
+149
View File
@@ -0,0 +1,149 @@
// Copyright 2024 Google Inc.
//
// 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 <cstddef>
#include <cstdint>
#include <cstdlib>
#include <iostream>
#include <memory>
#include <string>
#include <string_view>
#include "imageio/image_dec.h"
#include "src/dsp/cpu.h"
#include "tests/fuzzer/fuzz_utils.h"
#include "webp/decode.h"
#include "webp/encode.h"
#include "webp/types.h"
namespace {
const VP8CPUInfo default_VP8GetCPUInfo = fuzz_utils::VP8GetCPUInfo;
void EncTestImpl(WebPPicture& pic, uint32_t optimization_index, bool use_argb,
WebPConfig config,
const fuzz_utils::CropOrScaleParams& crop_or_scale_params) {
fuzz_utils::SetOptimization(default_VP8GetCPUInfo, optimization_index);
// Crop and scale.
if (!CropOrScale(&pic, crop_or_scale_params)) {
const WebPEncodingError error_code = pic.error_code;
if (error_code == VP8_ENC_ERROR_OUT_OF_MEMORY) return;
std::cerr << "CropOrScale failed. Error code: " << error_code << "\n";
std::abort();
}
// Skip the cruncher except on small images, it's likely to timeout.
if (config.lossless && config.quality == 100. && config.method == 6 &&
pic.width * pic.height >= 10000) {
config.lossless = 0;
}
// Encode.
WebPMemoryWriter memory_writer;
WebPMemoryWriterInit(&memory_writer);
pic.writer = WebPMemoryWrite;
pic.custom_ptr = &memory_writer;
if (!WebPEncode(&config, &pic)) {
const WebPEncodingError error_code = pic.error_code;
WebPMemoryWriterClear(&memory_writer);
if (error_code == VP8_ENC_ERROR_OUT_OF_MEMORY) return;
std::cerr << "WebPEncode failed. Error code: " << error_code << "\n";
std::abort();
}
// Try decoding the result.
int w, h;
const uint8_t* const out_data = memory_writer.mem;
const size_t out_size = memory_writer.size;
uint8_t* const rgba = WebPDecodeBGRA(out_data, out_size, &w, &h);
if (rgba == nullptr || w != pic.width || h != pic.height) {
std::cerr << "WebPDecodeBGRA failed.\n";
WebPFree(rgba);
WebPMemoryWriterClear(&memory_writer);
std::abort();
}
// Compare the results if exact encoding.
if (pic.use_argb && config.lossless && config.near_lossless == 100) {
const uint32_t* src1 = (const uint32_t*)rgba;
const uint32_t* src2 = pic.argb;
for (int y = 0; y < h; ++y, src1 += w, src2 += pic.argb_stride) {
for (int x = 0; x < w; ++x) {
uint32_t v1 = src1[x], v2 = src2[x];
if (!config.exact) {
if ((v1 & 0xff000000u) == 0 || (v2 & 0xff000000u) == 0) {
// Only keep alpha for comparison of fully transparent area.
v1 &= 0xff000000u;
v2 &= 0xff000000u;
}
}
if (v1 != v2) {
std::cerr << "Lossless compression failed pixel-exactness.\n";
WebPFree(rgba);
WebPMemoryWriterClear(&memory_writer);
std::abort();
}
}
}
}
WebPFree(rgba);
WebPMemoryWriterClear(&memory_writer);
WebPPictureFree(&pic);
}
// For open source compatibility, maybe_unused is necessary.
[[maybe_unused]] void EncFileTest(
std::string_view file, uint32_t optimization_index, bool use_argb,
WebPConfig config,
const fuzz_utils::CropOrScaleParams& crop_or_scale_params) {
// Init the source picture.
WebPPicture pic;
if (!WebPPictureInit(&pic)) {
std::cerr << "WebPPictureInit failed.\n";
std::abort();
}
pic.use_argb = use_argb;
const uint8_t* const file_data =
reinterpret_cast<const uint8_t*>(file.data());
if (fuzz_utils::IsImageTooBig(file_data, file.size())) return;
WebPImageReader reader = WebPGuessImageReader(file_data, file.size());
if (!reader(file_data, file.size(), &pic, 1, NULL)) return;
EncTestImpl(pic, optimization_index, use_argb, config, crop_or_scale_params);
}
void EncArbitraryTest(
fuzz_utils::WebPPictureCpp pic_cpp, uint32_t optimization_index,
bool use_argb, WebPConfig config,
const fuzz_utils::CropOrScaleParams& crop_or_scale_params) {
WebPPicture& pic = pic_cpp.ref();
EncTestImpl(pic, optimization_index, use_argb, config, crop_or_scale_params);
}
} // namespace
FUZZ_TEST(Enc, EncArbitraryTest)
.WithDomains(fuzz_utils::ArbitraryWebPPicture(),
/*optimization_index=*/
fuzztest::InRange<uint32_t>(0,
fuzz_utils::kMaxOptimizationIndex),
/*use_argb=*/fuzztest::Arbitrary<bool>(),
fuzz_utils::ArbitraryWebPConfig(),
fuzz_utils::ArbitraryCropOrScaleParams());
+17
View File
@@ -0,0 +1,17 @@
# https://developers.google.com/speed/webp/docs/riff_container
# FourCC
"ALPH"
"ANIM"
"ANMF"
"EXIF"
"ICCP"
"RIFF"
"VP8 "
"VP8L"
"VP8X"
"WEBP"
"XMP "
# VP8 signature
"\x9D\x01\x2A"
+198
View File
@@ -0,0 +1,198 @@
// Copyright 2024 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 "./fuzz_utils.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <string>
#include <string_view>
#include <tuple>
#include <vector>
#include "./img_alpha.h"
#include "./img_grid.h"
#include "./img_peak.h"
#include "src/dsp/cpu.h"
#include "webp/decode.h"
#include "webp/encode.h"
#include "webp/types.h"
namespace fuzz_utils {
WebPPicture GetSourcePicture(int image_index, bool use_argb) {
WebPPicture pic;
if (!WebPPictureInit(&pic)) std::abort();
pic.use_argb = use_argb;
// Pick a source picture.
const int kImagesWidth[] = {kImgAlphaWidth, kImgGridWidth, kImgPeakWidth};
const int kImagesHeight[] = {kImgAlphaHeight, kImgGridHeight, kImgPeakHeight};
const uint8_t* const image_data = kImagesData[image_index];
pic.width = kImagesWidth[image_index];
pic.height = kImagesHeight[image_index];
pic.argb_stride = pic.width * 4 * sizeof(uint8_t);
// Read the bytes.
if (!WebPPictureImportRGBA(&pic, image_data, pic.argb_stride)) std::abort();
return pic;
}
//------------------------------------------------------------------------------
int CropOrScale(WebPPicture* const pic, const CropOrScaleParams& params) {
if (pic == NULL) return 0;
#if !defined(WEBP_REDUCE_SIZE)
if (params.alter_input) {
if (params.crop_or_scale) {
const int cropped_width = std::max(1, pic->width / params.width_ratio);
const int cropped_height = std::max(1, pic->height / params.height_ratio);
const int cropped_left = (pic->width - cropped_width) / params.left_ratio;
const int cropped_top = (pic->height - cropped_height) / params.top_ratio;
return WebPPictureCrop(pic, cropped_left, cropped_top, cropped_width,
cropped_height);
} else {
const int scaled_width = 1 + (pic->width * params.width_ratio) / 8;
const int scaled_height = 1 + (pic->height * params.height_ratio) / 8;
return WebPPictureRescale(pic, scaled_width, scaled_height);
}
}
#else // defined(WEBP_REDUCE_SIZE)
(void)pic;
(void)params;
#endif // !defined(WEBP_REDUCE_SIZE)
return 1;
}
extern "C" VP8CPUInfo VP8GetCPUInfo;
static VP8CPUInfo GetCPUInfo;
static WEBP_INLINE int GetCPUInfoNoSSE41(CPUFeature feature) {
if (feature == kSSE4_1 || feature == kAVX) return 0;
return GetCPUInfo(feature);
}
static WEBP_INLINE int GetCPUInfoNoAVX(CPUFeature feature) {
if (feature == kAVX) return 0;
return GetCPUInfo(feature);
}
static WEBP_INLINE int GetCPUInfoForceSlowSSSE3(CPUFeature feature) {
if (feature == kSlowSSSE3 && GetCPUInfo(kSSE3)) {
return 1; // we have SSE3 -> force SlowSSSE3
}
return GetCPUInfo(feature);
}
static WEBP_INLINE int GetCPUInfoOnlyC(CPUFeature feature) {
(void)feature;
return 0;
}
void SetOptimization(VP8CPUInfo default_VP8GetCPUInfo, uint32_t index) {
assert(index <= kMaxOptimizationIndex);
GetCPUInfo = default_VP8GetCPUInfo;
const VP8CPUInfo kVP8CPUInfos[kMaxOptimizationIndex + 1] = {
GetCPUInfoOnlyC, GetCPUInfoForceSlowSSSE3, GetCPUInfoNoSSE41,
GetCPUInfoNoAVX, GetCPUInfo};
VP8GetCPUInfo = kVP8CPUInfos[index];
}
//------------------------------------------------------------------------------
std::vector<std::string> ReadFilesFromDirectory(std::string_view dir) {
std::vector<std::tuple<std::string>> tuples =
fuzztest::ReadFilesFromDirectory(dir);
std::vector<std::string> strings(tuples.size());
for (size_t i = 0; i < tuples.size(); ++i) {
using std::swap;
swap(std::get<0>(tuples[i]), strings[i]);
}
return strings;
}
//------------------------------------------------------------------------------
// The code in this section is copied from
// https://github.com/webmproject/sjpeg/blob/
// 1c025b3dbc2246de3e1d7c287970f1a01291800f/src/jpeg_tools.cc#L47
// (same license as this file).
namespace {
// Constants below are marker codes defined in JPEG spec
// ISO/IEC 10918-1 : 1993(E) Table B.1
// See also: http://www.w3.org/Graphics/JPEG/itu-t81.pdf
#define M_SOF0 0xffc0
#define M_SOF1 0xffc1
const uint8_t* GetSOFData(const uint8_t* src, int size) {
if (src == NULL) return NULL;
const uint8_t* const end = src + size - 8; // 8 bytes of safety, for marker
src += 2; // skip M_SOI
for (; src < end && *src != 0xff; ++src) { /* search first 0xff marker */
}
while (src < end) {
const uint32_t marker = static_cast<uint32_t>((src[0] << 8) | src[1]);
if (marker == M_SOF0 || marker == M_SOF1) return src;
const size_t s = 2 + ((src[2] << 8) | src[3]);
src += s;
}
return NULL; // No SOF marker found
}
bool SjpegDimensions(const uint8_t* src0, size_t size, int* width, int* height,
int* is_yuv420) {
if (width == NULL || height == NULL) return false;
const uint8_t* src = GetSOFData(src0, size);
const size_t left_over = size - (src - src0);
if (src == NULL || left_over < 8 + 3 * 1) return false;
if (height != NULL) *height = (src[5] << 8) | src[6];
if (width != NULL) *width = (src[7] << 8) | src[8];
if (is_yuv420 != NULL) {
const size_t nb_comps = src[9];
*is_yuv420 = (nb_comps == 3);
if (left_over < 11 + 3 * nb_comps) return false;
for (int c = 0; *is_yuv420 && c < 3; ++c) {
const int expected_dim = (c == 0 ? 0x22 : 0x11);
*is_yuv420 &= (src[11 + c * 3] == expected_dim);
}
}
return true;
}
} // namespace
//------------------------------------------------------------------------------
bool IsImageTooBig(const uint8_t* data, size_t size) {
int width, height, components;
if (SjpegDimensions(data, size, &width, &height, &components) ||
WebPGetInfo(data, size, &width, &height)) {
// Look at the number of 8x8px blocks rather than the overall pixel count
// when comparing to memory and duration thresholds.
const size_t ceiled_width = ((size_t)width + 7) / 8 * 8;
const size_t ceiled_height = ((size_t)height + 7) / 8 * 8;
// Threshold to avoid out-of-memory and timeout issues.
// The threshold is arbitrary but below the fuzzer limit of 2 GB.
// The value cannot be 2 GB because of the added memory by MSAN.
if (ceiled_width * ceiled_height > kFuzzPxLimit) return true;
}
return false;
}
} // namespace fuzz_utils
+434
View File
@@ -0,0 +1,434 @@
// Copyright 2018-2024 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.
//
////////////////////////////////////////////////////////////////////////////////
#ifndef WEBP_TESTS_FUZZER_FUZZ_UTILS_H_
#define WEBP_TESTS_FUZZER_FUZZ_UTILS_H_
#include <algorithm>
#include <array>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include "./img_alpha.h"
#include "./img_grid.h"
#include "./img_peak.h"
#include "fuzztest/fuzztest.h"
#include "src/dsp/cpu.h"
#include "src/webp/decode.h"
#include "src/webp/encode.h"
#include "src/webp/types.h"
namespace fuzz_utils {
//------------------------------------------------------------------------------
// Arbitrary limits to prevent OOM, timeout, or slow execution.
// The decoded image size, and for animations additionally the canvas size.
// Enabling some sanitizers slow down runtime significantly.
// Use a very low threshold in this case to avoid timeouts.
#if defined(__SANITIZE_ADDRESS__) // GCC
static const size_t kFuzzPxLimit = 1024 * 1024 / 10;
#elif !defined(__has_feature) // Clang
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
// Demuxed or decoded animation frames.
static const int kFuzzFrameLimit = 3;
// Reads and sums (up to) 128 spread-out bytes.
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);
// Struct to use in a unique_ptr to free the memory.
struct UniquePtrDeleter {
void operator()(WebPMemoryWriter* writer) const {
WebPMemoryWriterClear(writer);
}
void operator()(WebPPicture* pic) const { WebPPictureFree(pic); }
void operator()(WebPDecoderConfig* config) const {
WebPFreeDecBuffer(&config->output);
}
};
// Like WebPPicture but with no C array.
// This can be removed once b/294098900 is fixed.
struct WebPPictureCpp {
inline WebPPictureCpp(int use_argb, WebPEncCSP colorspace, int width,
int height, uint8_t* y, uint8_t* u, uint8_t* v,
int y_stride, int uv_stride, uint8_t* a, int a_stride,
uint32_t* argb, int argb_stride, void* memory,
void* memory_argb) {
pic.reset(new WebPPicture(), [](WebPPicture* pic) {
WebPPictureFree(pic);
delete pic;
});
if (!WebPPictureInit(pic.get())) assert(false);
pic->use_argb = use_argb;
pic->colorspace = colorspace;
pic->width = width;
pic->height = height;
pic->y = y;
pic->u = u;
pic->v = v;
pic->a = a;
pic->y_stride = y_stride;
pic->uv_stride = uv_stride;
pic->a_stride = a_stride;
pic->argb = argb;
pic->argb_stride = argb_stride;
pic->memory_ = memory;
pic->memory_argb_ = memory_argb;
}
WebPPicture& ref() const { return const_cast<WebPPicture&>(*pic); }
std::shared_ptr<WebPPicture> pic;
};
static inline auto ArbitraryWebPPicture() {
return fuzztest::FlatMap(
// colorspace of 0 is use_argb, 1 is YUV420, 2 is YUV420A.
[](int colorspace, int width, int height) {
const int uv_width = (int)(((int64_t)width + 1) >> 1);
const int uv_height = (int)(((int64_t)height + 1) >> 1);
// Create a domain for the vector that strictly obeys w * h * 4.
size_t size = width * height;
if (colorspace == 0) size *= 4;
if (colorspace == 1) size += 2 * uv_width * uv_height;
if (colorspace == 2) size += 2 * uv_width * uv_height + size;
auto DataDomain =
fuzztest::VectorOf(fuzztest::Arbitrary<uint8_t>()).WithSize(size);
// Map the vector domain back into our Image struct, injecting w and h
return fuzztest::Map(
[colorspace, width,
height](const std::vector<uint8_t>& data) -> WebPPictureCpp {
WebPPicture pic;
if (!WebPPictureInit(&pic)) assert(false);
pic.use_argb = colorspace == 0 ? 1 : 0;
pic.colorspace = static_cast<WebPEncCSP>(
colorspace <= 1 ? WEBP_YUV420 : WEBP_YUV420A);
pic.width = width;
pic.height = height;
if (!WebPPictureAlloc(&pic)) assert(false);
size_t size = width * height;
if (pic.use_argb) {
std::copy(data.begin(), data.begin() + size,
(uint32_t*)pic.argb);
} else {
// Y.
auto iter = data.begin();
std::copy(iter, iter + size, (uint8_t*)pic.y);
iter += size;
// A.
if ((int)pic.colorspace & WEBP_CSP_ALPHA_BIT) {
std::copy(iter, iter + size, (uint8_t*)pic.a);
iter += size;
}
// U and V.
const int uv_width = (int)(((int64_t)width + 1) >> 1);
const int uv_height = (int)(((int64_t)height + 1) >> 1);
size = uv_width * uv_height;
std::copy(iter, iter + size, (uint8_t*)pic.u);
iter += size;
std::copy(iter, iter + size, (uint8_t*)pic.v);
}
return WebPPictureCpp(pic.use_argb, pic.colorspace, pic.width,
pic.height, pic.y, pic.u, pic.v,
pic.y_stride, pic.uv_stride, pic.a,
pic.a_stride, pic.argb, pic.argb_stride,
pic.memory_, pic.memory_argb_);
},
DataDomain);
},
/*colorspace=*/fuzztest::InRange<int>(0, 2),
/*width=*/fuzztest::InRange<int>(1, 128),
/*height=*/fuzztest::InRange<int>(1, 128));
}
static inline auto ArbitraryWebPPictureFromIndex() {
return fuzztest::Map(
[](int index, bool use_argb) -> WebPPictureCpp {
// Map the vector domain back into our Image struct, injecting w and h
WebPPicture pic = fuzz_utils::GetSourcePicture(index, use_argb);
return WebPPictureCpp(use_argb, pic.colorspace, pic.width, pic.height,
pic.y, pic.u, pic.v, pic.y_stride, pic.uv_stride,
pic.a, pic.a_stride, pic.argb, pic.argb_stride,
pic.memory_, pic.memory_argb_);
},
/*index=*/fuzztest::InRange<int>(0, fuzz_utils::kNumSourceImages - 1),
/*use_argb=*/fuzztest::Arbitrary<bool>());
}
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)) assert(false);
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)) assert(false);
return config;
},
/*lossless=*/fuzztest::InRange<int>(0, 1),
/*quality=*/fuzztest::InRange<int>(0, 100),
/*method=*/fuzztest::InRange<int>(0, 6),
/*image_hint=*/fuzztest::InRange<int>(0, WEBP_HINT_LAST - 1),
/*segments=*/fuzztest::InRange<int>(1, 4),
/*sns_strength=*/fuzztest::InRange<int>(0, 100),
/*filter_strength=*/fuzztest::InRange<int>(0, 100),
/*filter_sharpness=*/fuzztest::InRange<int>(0, 7),
/*filter_type=*/fuzztest::InRange<int>(0, 1),
/*autofilter=*/fuzztest::InRange<int>(0, 1),
/*alpha_compression=*/fuzztest::InRange<int>(0, 1),
/*alpha_filtering=*/fuzztest::InRange<int>(0, 2),
/*alpha_quality=*/fuzztest::InRange<int>(0, 100),
/*pass=*/fuzztest::InRange<int>(1, 10),
/*preprocessing=*/fuzztest::InRange<int>(0, 2),
/*partitions=*/fuzztest::InRange<int>(0, 3),
/*partition_limit=*/fuzztest::InRange<int>(0, 10),
/*emulate_jpeg_size=*/fuzztest::InRange<int>(0, 1),
/*thread_level=*/fuzztest::InRange<int>(0, 1),
/*low_memory=*/fuzztest::InRange<int>(0, 1),
/*near_lossless=*/fuzztest::InRange<int>(0, 5),
/*exact=*/fuzztest::InRange<int>(0, 1),
/*use_delta_palette=*/fuzztest::InRange<int>(0, 1),
/*use_sharp_yuv=*/fuzztest::InRange<int>(0, 1));
}
// Like WebPDecoderOptions but with no C array.
// This can be removed once b/294098900 is fixed.
struct WebPDecoderOptionsCpp {
int bypass_filtering;
int no_fancy_upsampling;
int use_cropping;
int crop_left, crop_top;
int crop_width, crop_height;
int use_scaling;
int scaled_width, scaled_height;
int use_threads;
int dithering_strength;
int flip;
int alpha_dithering_strength;
std::array<uint32_t, 5> pad;
};
static inline auto ArbitraryValidWebPDecoderOptions() {
return fuzztest::Map(
[](int bypass_filtering, int no_fancy_upsampling, int use_cropping,
int crop_left, int crop_top, int crop_width, int crop_height,
int use_scaling, int scaled_width, int scaled_height, int use_threads,
int dithering_strength, int flip,
int alpha_dithering_strength) -> WebPDecoderOptionsCpp {
WebPDecoderOptions options;
options.bypass_filtering = bypass_filtering;
options.no_fancy_upsampling = no_fancy_upsampling;
options.use_cropping = use_cropping;
options.crop_left = crop_left;
options.crop_top = crop_top;
options.crop_width = crop_width;
options.crop_height = crop_height;
options.use_scaling = use_scaling;
options.scaled_width = scaled_width;
options.scaled_height = scaled_height;
options.use_threads = use_threads;
options.dithering_strength = dithering_strength;
options.flip = flip;
options.alpha_dithering_strength = alpha_dithering_strength;
WebPDecoderConfig config;
if (!WebPInitDecoderConfig(&config)) assert(false);
config.options = options;
if (!WebPValidateDecoderConfig(&config)) assert(false);
WebPDecoderOptionsCpp options_cpp;
std::memcpy(&options_cpp, &options, sizeof(options));
return options_cpp;
},
/*bypass_filtering=*/fuzztest::InRange<int>(0, 1),
/*no_fancy_upsampling=*/fuzztest::InRange<int>(0, 1),
/*use_cropping=*/fuzztest::InRange<int>(0, 1),
/*crop_left=*/fuzztest::InRange<int>(0, 10),
/*crop_top=*/fuzztest::InRange<int>(0, 10),
/*crop_width=*/fuzztest::InRange<int>(1, 10),
/*crop_height=*/fuzztest::InRange<int>(1, 10),
/*use_scaling=*/fuzztest::InRange<int>(0, 1),
/*scaled_width=*/fuzztest::InRange<int>(1, 10),
/*scaled_height=*/fuzztest::InRange<int>(1, 10),
/*use_threads=*/fuzztest::InRange<int>(0, 1),
/*dithering_strength=*/fuzztest::InRange<int>(0, 100),
/*flip=*/fuzztest::InRange<int>(0, 1),
/*alpha_dithering_strength=*/fuzztest::InRange<int>(0, 100));
}
static inline auto ArbitraryWebPDecoderOptions() {
return fuzztest::Map(
[](int bypass_filtering, int no_fancy_upsampling, int use_cropping,
int crop_left, int crop_top, int crop_width, int crop_height,
int use_scaling, int scaled_width, int scaled_height, int use_threads,
int dithering_strength, int flip,
int alpha_dithering_strength) -> WebPDecoderOptionsCpp {
WebPDecoderOptions options;
options.bypass_filtering = bypass_filtering;
options.no_fancy_upsampling = no_fancy_upsampling;
options.use_cropping = use_cropping;
options.crop_left = crop_left;
options.crop_top = crop_top;
options.crop_width = crop_width;
options.crop_height = crop_height;
options.use_scaling = use_scaling;
options.scaled_width = scaled_width;
options.scaled_height = scaled_height;
options.use_threads = use_threads;
options.dithering_strength = dithering_strength;
options.flip = flip;
options.alpha_dithering_strength = alpha_dithering_strength;
WebPDecoderOptionsCpp options_cpp;
std::memcpy(&options_cpp, &options, sizeof(options));
return options_cpp;
},
/*bypass_filtering=*/fuzztest::Arbitrary<int>(),
/*no_fancy_upsampling=*/fuzztest::Arbitrary<int>(),
/*use_cropping=*/fuzztest::Arbitrary<int>(),
/*crop_left=*/fuzztest::Arbitrary<int>(),
/*crop_top=*/fuzztest::Arbitrary<int>(),
/*crop_width=*/fuzztest::Arbitrary<int>(),
/*crop_height=*/fuzztest::Arbitrary<int>(),
/*use_scaling=*/fuzztest::Arbitrary<int>(),
/*scaled_width=*/fuzztest::Arbitrary<int>(),
/*scaled_height=*/fuzztest::Arbitrary<int>(),
/*use_threads=*/fuzztest::Arbitrary<int>(),
/*dithering_strength=*/fuzztest::Arbitrary<int>(),
/*flip=*/fuzztest::Arbitrary<int>(),
/*alpha_dithering_strength=*/fuzztest::Arbitrary<int>());
}
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))));
}
// Crops or scales a picture according to the given params.
int CropOrScale(WebPPicture* pic, const CropOrScaleParams& params);
// Imposes a level of optimization among one of the kMaxOptimizationIndex+1
// possible values: OnlyC, ForceSlowSSSE3, NoSSE41, NoAVX, default.
static constexpr uint32_t kMaxOptimizationIndex = 4;
void SetOptimization(VP8CPUInfo default_VP8GetCPUInfo, uint32_t index);
//------------------------------------------------------------------------------
// See https://developers.google.com/speed/webp/docs/riff_container.
static constexpr size_t kMaxWebPFileSize = (1ull << 32) - 2; // 4 GiB - 2
std::vector<std::string> GetDictionaryFromFiles(
const std::vector<std::string_view>& file_paths);
// Checks whether the binary blob containing a JPEG or WebP is too big for the
// fuzzer.
bool IsImageTooBig(const uint8_t* data, size_t size);
} // namespace fuzz_utils
#endif // WEBP_TESTS_FUZZER_FUZZ_UTILS_H_
+78
View File
@@ -0,0 +1,78 @@
// Copyright 2023 Google Inc.
//
// 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 <cstddef>
#include <cstdint>
#include <cstring>
#include <string_view>
#include "./fuzz_utils.h"
#include "src/dec/vp8li_dec.h"
#include "src/utils/bit_reader_utils.h"
#include "src/utils/huffman_utils.h"
#include "src/utils/utils.h"
#include "webp/format_constants.h"
namespace {
void HuffmanTest(std::string_view blob) {
const uint8_t* const data = reinterpret_cast<const uint8_t*>(blob.data());
const size_t size = blob.size();
// Number of bits to initialize data.
static const int kColorCacheBitsBits = 4;
// 'num_htree_groups' is contained in the RG channel, hence 16 bits.
static const int kNumHtreeGroupsBits = 16;
if (size * sizeof(*data) < kColorCacheBitsBits + kNumHtreeGroupsBits) {
return;
}
// A non-NULL mapping brings minor changes that are tested by the normal
// fuzzer.
int* const mapping = NULL;
HuffmanTables huffman_tables;
memset(&huffman_tables, 0, sizeof(huffman_tables));
HTreeGroup* htree_groups = NULL;
int num_htree_groups, num_htree_groups_max, color_cache_bits;
VP8LBitReader* br;
VP8LDecoder* dec = VP8LNew();
if (dec == NULL) goto Error;
br = &dec->br;
VP8LInitBitReader(br, data, size);
color_cache_bits = VP8LReadBits(br, kColorCacheBitsBits);
if (color_cache_bits < 1 || color_cache_bits > MAX_CACHE_BITS) goto Error;
num_htree_groups = VP8LReadBits(br, kNumHtreeGroupsBits);
// 'num_htree_groups' cannot be 0 as it is built from a non-empty image.
if (num_htree_groups == 0) goto Error;
// This variable is only useful when mapping is not NULL.
num_htree_groups_max = num_htree_groups;
(void)ReadHuffmanCodesHelper(color_cache_bits, num_htree_groups,
num_htree_groups_max, mapping, dec,
&huffman_tables, &htree_groups);
Error:
WebPSafeFree(mapping);
VP8LHtreeGroupsFree(htree_groups);
VP8LHuffmanTablesDeallocate(&huffman_tables);
VP8LDelete(dec);
}
} // namespace
FUZZ_TEST(Huffman, HuffmanTest).WithDomains(fuzztest::String());
+79
View File
@@ -0,0 +1,79 @@
// Copyright 2024 Google Inc.
//
// 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.
//
////////////////////////////////////////////////////////////////////////////////
// Fuzzing of libwebp's image readers
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <iostream>
#include <string_view>
#include "./nalloc.h"
#include "imageio/image_dec.h"
#include "imageio/metadata.h"
#include "src/webp/encode.h"
#include "tests/fuzzer/fuzz_utils.h"
namespace {
void TestReader(const uint8_t* data, size_t size, WebPImageReader reader,
bool keep_alpha, bool use_argb) {
WebPPicture pic;
if (!WebPPictureInit(&pic)) {
std::cerr << "WebPPictureInit failed" << std::endl;
std::abort();
}
nalloc_init(nullptr);
nalloc_start(data, size);
Metadata metadata;
MetadataInit(&metadata);
pic.use_argb = use_argb ? 1 : 0;
if (!fuzz_utils::IsImageTooBig(data, size)) {
(void)(*reader)(data, size, &pic, keep_alpha ? 1 : 0, &metadata);
}
WebPPictureFree(&pic);
MetadataFree(&metadata);
nalloc_end();
}
constexpr WebPInputFileFormat kUnknown = WEBP_UNSUPPORTED_FORMAT;
void Decode(std::string_view arbitrary_bytes, WebPInputFileFormat format,
bool keep_alpha, bool use_argb) {
const uint8_t* data =
reinterpret_cast<const uint8_t*>(arbitrary_bytes.data());
const size_t size = arbitrary_bytes.size();
if (format == kUnknown) {
(void)WebPGuessImageType(data, size); // shouldn't fail
TestReader(data, size, WebPGuessImageReader(data, size), keep_alpha,
use_argb);
} else {
TestReader(data, size, WebPGetImageReader(format), keep_alpha, use_argb);
}
}
FUZZ_TEST(ImageIOSuite, Decode)
.WithDomains(fuzztest::String().WithMaxSize(fuzz_utils::kMaxWebPFileSize +
1),
fuzztest::ElementOf<WebPInputFileFormat>(
{WEBP_PNG_FORMAT, WEBP_JPEG_FORMAT, WEBP_TIFF_FORMAT,
WEBP_WEBP_FORMAT, WEBP_PNM_FORMAT, kUnknown}),
/*keep_alpha=*/fuzztest::Arbitrary<bool>(),
/*use_argb=*/fuzztest::Arbitrary<bool>());
} // namespace
+371
View File
@@ -0,0 +1,371 @@
// Copyright 2018 Google Inc.
//
// 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.
//
////////////////////////////////////////////////////////////////////////////////
#ifndef WEBP_TESTS_FUZZER_IMG_ALPHA_H_
#define WEBP_TESTS_FUZZER_IMG_ALPHA_H_
#include <stdint.h>
static const int kImgAlphaWidth = 32;
static const int kImgAlphaHeight = 32;
/*Pixel format: Red: 8 bit, Green: 8 bit, Blue: 8 bit, Fix 0xFF: 8 bit*/
static const uint8_t kImgAlphaData[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfe, 0xfe, 0xfe, 0xff, 0xfe, 0xfe, 0xfd, 0xff, 0xfe, 0xfd, 0xfc, 0xff,
0xfe, 0xfd, 0xfb, 0xff, 0xfe, 0xfc, 0xfb, 0xff, 0xfe, 0xfc, 0xfa, 0xff,
0xfe, 0xfc, 0xf9, 0xff, 0xfe, 0xfb, 0xf8, 0xff, 0xfe, 0xfb, 0xf7, 0xff,
0xfe, 0xfb, 0xf7, 0xff, 0xfe, 0xfa, 0xf6, 0xff, 0xfe, 0xf9, 0xf5, 0xff,
0xfd, 0xf9, 0xf3, 0xff, 0xfd, 0xf8, 0xf2, 0xff, 0xfd, 0xf7, 0xf1, 0xff,
0xfc, 0xf7, 0xf0, 0xff, 0xfc, 0xf6, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfe, 0xfe, 0xfd, 0xff,
0xfe, 0xfd, 0xfc, 0xff, 0xfe, 0xfd, 0xfb, 0xff, 0xfe, 0xfc, 0xfa, 0xff,
0xfe, 0xfc, 0xfa, 0xff, 0xfe, 0xfb, 0xf9, 0xff, 0xfe, 0xfb, 0xf8, 0xff,
0xfe, 0xfb, 0xf7, 0xff, 0xfe, 0xfa, 0xf7, 0xff, 0xfe, 0xfa, 0xf5, 0xff,
0xfe, 0xfa, 0xf5, 0xff, 0xfd, 0xf9, 0xf4, 0xff, 0xfd, 0xf8, 0xf2, 0xff,
0xfc, 0xf7, 0xf1, 0xff, 0xfc, 0xf7, 0xf0, 0xff, 0xfc, 0xf7, 0xef, 0xff,
0xfc, 0xf6, 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfe, 0xfe, 0xfd, 0xff,
0xfe, 0xfd, 0xfd, 0xff, 0xfe, 0xfd, 0xfc, 0xff, 0xfe, 0xfd, 0xfb, 0xff,
0xfe, 0xfc, 0xfa, 0xff, 0xfe, 0xfc, 0xfa, 0xff, 0xfe, 0xfc, 0xf9, 0xff,
0xfe, 0xfb, 0xf8, 0xff, 0xfe, 0xfb, 0xf7, 0xff, 0xfe, 0xfb, 0xf6, 0xff,
0xfe, 0xfa, 0xf5, 0xff, 0xfe, 0xfa, 0xf5, 0xff, 0xfe, 0xf9, 0xf4, 0xff,
0xfe, 0xf8, 0xf3, 0xff, 0xfd, 0xf8, 0xf2, 0xff, 0xfc, 0xf7, 0xf1, 0xff,
0xfc, 0xf5, 0xf0, 0xff, 0xfc, 0xf6, 0xee, 0xff, 0xfc, 0xf5, 0xed, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff,
0xfc, 0xfb, 0xfb, 0xff, 0xfd, 0xfc, 0xfc, 0xff, 0xfe, 0xfd, 0xfb, 0xff,
0xfe, 0xfc, 0xfa, 0xff, 0xfe, 0xfc, 0xfa, 0xff, 0xfe, 0xfc, 0xf9, 0xff,
0xfe, 0xfb, 0xf8, 0xff, 0xfe, 0xfb, 0xf8, 0xff, 0xfe, 0xfb, 0xf7, 0xff,
0xfe, 0xfb, 0xf6, 0xff, 0xfe, 0xfa, 0xf5, 0xff, 0xfe, 0xfa, 0xf5, 0xff,
0xfe, 0xf9, 0xf4, 0xff, 0xfe, 0xf9, 0xf3, 0xff, 0xfe, 0xf8, 0xf2, 0xff,
0xfd, 0xf7, 0xf1, 0xff, 0xfc, 0xf6, 0xf0, 0xff, 0xfc, 0xf6, 0xee, 0xff,
0xfc, 0xf5, 0xec, 0xff, 0xfb, 0xf5, 0xec, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfc, 0xfc, 0xfc, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xfa, 0xf9, 0xf9, 0xff,
0xf7, 0xf6, 0xf6, 0xff, 0xfd, 0xfc, 0xfa, 0xff, 0xfe, 0xfc, 0xfa, 0xff,
0xfe, 0xfc, 0xf9, 0xff, 0xfe, 0xfb, 0xf9, 0xff, 0xfe, 0xfb, 0xf7, 0xff,
0xfe, 0xfb, 0xf7, 0xff, 0xfe, 0xfb, 0xf6, 0xff, 0xfe, 0xfa, 0xf5, 0xff,
0xfe, 0xfa, 0xf5, 0xff, 0xfe, 0xfa, 0xf3, 0xff, 0xfe, 0xfa, 0xf4, 0xfb,
0xfe, 0xf9, 0xf4, 0xeb, 0xfe, 0xfb, 0xf6, 0xdc, 0xfd, 0xfa, 0xf6, 0xcf,
0xfd, 0xfa, 0xf5, 0xcc, 0xfc, 0xf9, 0xf4, 0xcb, 0xfd, 0xf8, 0xf3, 0xc7,
0xfc, 0xf8, 0xf2, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfd, 0xfd, 0xfd, 0xff, 0xfb, 0xfa, 0xfa, 0xff, 0xf8, 0xf7, 0xf7, 0xff,
0xf6, 0xf4, 0xf4, 0xff, 0xf7, 0xf5, 0xf5, 0xff, 0xf5, 0xf5, 0xf4, 0xff,
0xf8, 0xf7, 0xf7, 0xff, 0xfd, 0xfb, 0xf8, 0xff, 0xfe, 0xfb, 0xf8, 0xff,
0xfe, 0xfb, 0xf7, 0xff, 0xfe, 0xfb, 0xf7, 0xff, 0xfe, 0xfa, 0xf6, 0xff,
0xfe, 0xfa, 0xf5, 0xff, 0xfe, 0xfa, 0xf4, 0xff, 0xfd, 0xfa, 0xf4, 0xfc,
0xfe, 0xfc, 0xf9, 0xcf, 0xff, 0xff, 0xff, 0xaf, 0xff, 0xff, 0xff, 0xa8,
0xff, 0xff, 0xff, 0xa4, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0x9b,
0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x8b,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfd, 0xfc, 0xfc, 0xff, 0xfa, 0xf9, 0xf9, 0xff,
0xf6, 0xf5, 0xf4, 0xff, 0xf5, 0xf3, 0xf3, 0xff, 0xf4, 0xf2, 0xf1, 0xff,
0xf2, 0xf1, 0xf0, 0xff, 0xf2, 0xf0, 0xf0, 0xff, 0xf0, 0xee, 0xee, 0xff,
0xf1, 0xf0, 0xef, 0xff, 0xfe, 0xfb, 0xf8, 0xff, 0xfe, 0xfb, 0xf6, 0xff,
0xfe, 0xfa, 0xf6, 0xff, 0xfe, 0xfa, 0xf5, 0xff, 0xfe, 0xfb, 0xf4, 0xff,
0xfe, 0xfb, 0xf5, 0xf3, 0xff, 0xfe, 0xfe, 0xb4, 0xff, 0xff, 0xff, 0xac,
0xff, 0xff, 0xff, 0xa7, 0xff, 0xff, 0xff, 0xa3, 0xff, 0xff, 0xff, 0x9c,
0xff, 0xff, 0xff, 0x98, 0xff, 0xff, 0xff, 0x93, 0xff, 0xff, 0xff, 0x8f,
0xff, 0xff, 0xff, 0x88, 0xff, 0xff, 0xff, 0x84, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfc, 0xfb, 0xfb, 0xff,
0xf9, 0xf8, 0xf8, 0xff, 0xf6, 0xf5, 0xf4, 0xff, 0xf3, 0xf1, 0xf1, 0xff,
0xf0, 0xed, 0xed, 0xff, 0xef, 0xec, 0xeb, 0xff, 0xee, 0xeb, 0xeb, 0xff,
0xf0, 0xee, 0xee, 0xff, 0xea, 0xe7, 0xe7, 0xff, 0xec, 0xe9, 0xe9, 0xff,
0xf5, 0xf2, 0xf0, 0xff, 0xfe, 0xfb, 0xf6, 0xff, 0xfe, 0xfb, 0xf5, 0xff,
0xfe, 0xfa, 0xf4, 0xff, 0xfe, 0xfb, 0xf6, 0xeb, 0xff, 0xff, 0xff, 0xaf,
0xff, 0xff, 0xff, 0xab, 0xff, 0xff, 0xff, 0xa4, 0xff, 0xff, 0xff, 0xa0,
0xff, 0xff, 0xff, 0x9b, 0xff, 0xff, 0xff, 0x97, 0xff, 0xff, 0xff, 0x90,
0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x87, 0xff, 0xff, 0xff, 0x83,
0xff, 0xff, 0xff, 0x7c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfc, 0xfc, 0xff,
0xfb, 0xfb, 0xfa, 0xff, 0xf8, 0xf6, 0xf6, 0xff, 0xf4, 0xf3, 0xf2, 0xff,
0xf2, 0xf0, 0xf0, 0xff, 0xef, 0xec, 0xeb, 0xff, 0xef, 0xec, 0xeb, 0xff,
0xeb, 0xe7, 0xe6, 0xff, 0xea, 0xe6, 0xe5, 0xff, 0xeb, 0xe8, 0xe8, 0xff,
0xe9, 0xe6, 0xe7, 0xff, 0xe5, 0xe2, 0xe2, 0xff, 0xed, 0xeb, 0xeb, 0xff,
0xf7, 0xf5, 0xf2, 0xff, 0xfe, 0xfa, 0xf5, 0xff, 0xfe, 0xfb, 0xf5, 0xf8,
0xff, 0xff, 0xff, 0xac, 0xff, 0xff, 0xff, 0xa8, 0xff, 0xff, 0xff, 0xa3,
0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0x98, 0xff, 0xff, 0xff, 0x94,
0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0x8b, 0xff, 0xff, 0xff, 0x84,
0xff, 0xff, 0xff, 0x80, 0xff, 0xff, 0xff, 0x7c, 0xff, 0xff, 0xff, 0x77,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfc, 0xfc, 0xfc, 0xff, 0xf8, 0xf7, 0xf7, 0xff, 0xf6, 0xf5, 0xf4, 0xff,
0xf3, 0xf1, 0xf0, 0xff, 0xf1, 0xef, 0xef, 0xff, 0xef, 0xed, 0xec, 0xff,
0xec, 0xe8, 0xe7, 0xff, 0xe9, 0xe6, 0xe6, 0xff, 0xec, 0xe9, 0xe9, 0xff,
0xe4, 0xe0, 0xdf, 0xff, 0xec, 0xe9, 0xe9, 0xff, 0xea, 0xe6, 0xe6, 0xff,
0xe6, 0xe2, 0xe2, 0xff, 0xea, 0xe8, 0xe8, 0xff, 0xec, 0xe8, 0xe7, 0xff,
0xfc, 0xf9, 0xf4, 0xff, 0xfe, 0xfd, 0xfa, 0xc3, 0xff, 0xff, 0xff, 0xa7,
0xff, 0xff, 0xff, 0xa0, 0xff, 0xff, 0xff, 0x9c, 0xff, 0xff, 0xff, 0x97,
0xff, 0xff, 0xff, 0x93, 0xff, 0xff, 0xff, 0x8c, 0xfe, 0xfc, 0xf9, 0xa3,
0xfc, 0xfb, 0xf5, 0xb0, 0xfc, 0xf9, 0xf1, 0xbb, 0xfb, 0xf8, 0xf1, 0xb8,
0xfb, 0xf8, 0xef, 0xb4, 0xfb, 0xf9, 0xf2, 0xa4, 0xff, 0xff, 0xff, 0xff,
0xfe, 0xfe, 0xfe, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xf8, 0xf7, 0xf7, 0xff,
0xf5, 0xf3, 0xf3, 0xff, 0xf1, 0xef, 0xef, 0xff, 0xef, 0xec, 0xeb, 0xff,
0xeb, 0xe7, 0xe7, 0xff, 0xea, 0xe7, 0xe6, 0xff, 0xe7, 0xe3, 0xe2, 0xff,
0xe4, 0xdf, 0xde, 0xff, 0xe6, 0xe2, 0xe2, 0xff, 0xe4, 0xe1, 0xe0, 0xff,
0xe6, 0xe3, 0xe2, 0xff, 0xe0, 0xdc, 0xdc, 0xff, 0xe3, 0xdf, 0xdf, 0xff,
0xe8, 0xe5, 0xe5, 0xff, 0xe4, 0xe1, 0xe2, 0xff, 0xec, 0xe8, 0xe5, 0xf8,
0xff, 0xff, 0xff, 0xa4, 0xff, 0xff, 0xff, 0xa0, 0xff, 0xff, 0xff, 0x9b,
0xff, 0xff, 0xff, 0x97, 0xff, 0xff, 0xff, 0x90, 0xfe, 0xfe, 0xfb, 0x9c,
0xfc, 0xf9, 0xef, 0xf7, 0xfc, 0xf8, 0xed, 0xff, 0xfc, 0xf7, 0xeb, 0xff,
0xfb, 0xf7, 0xeb, 0xff, 0xfa, 0xf6, 0xe9, 0xff, 0xfa, 0xf5, 0xe7, 0xff,
0xf8, 0xf4, 0xe5, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfa, 0xfa, 0xfa, 0xff,
0xfc, 0xfc, 0xfc, 0xff, 0xf8, 0xf7, 0xf7, 0xff, 0xf1, 0xef, 0xee, 0xff,
0xed, 0xea, 0xe9, 0xff, 0xea, 0xe6, 0xe5, 0xff, 0xe7, 0xe3, 0xe2, 0xff,
0xe4, 0xe0, 0xdf, 0xff, 0xe3, 0xde, 0xdd, 0xff, 0xe2, 0xde, 0xdd, 0xff,
0xe5, 0xe1, 0xe1, 0xff, 0xde, 0xda, 0xda, 0xff, 0xe0, 0xdd, 0xdc, 0xff,
0xe1, 0xdd, 0xdd, 0xff, 0xe3, 0xe0, 0xdf, 0xff, 0xe4, 0xe1, 0xe1, 0xff,
0xe3, 0xe0, 0xe0, 0xff, 0xec, 0xea, 0xea, 0xe8, 0xff, 0xff, 0xff, 0x9f,
0xff, 0xff, 0xff, 0x98, 0xff, 0xff, 0xff, 0x93, 0xff, 0xff, 0xff, 0x8f,
0xfe, 0xfe, 0xfe, 0x8c, 0xfd, 0xfb, 0xef, 0xff, 0xfd, 0xfb, 0xed, 0xff,
0xfd, 0xf8, 0xec, 0xff, 0xfc, 0xf8, 0xeb, 0xff, 0xfc, 0xf7, 0xea, 0xff,
0xfb, 0xf6, 0xe9, 0xff, 0xfa, 0xf6, 0xe7, 0xff, 0xfa, 0xf5, 0xe5, 0xff,
0xfa, 0xfa, 0xfa, 0xff, 0xf8, 0xf7, 0xf8, 0xff, 0xf6, 0xf6, 0xf6, 0xff,
0xf1, 0xf0, 0xf0, 0xff, 0xed, 0xec, 0xec, 0xff, 0xe9, 0xe6, 0xe5, 0xff,
0xe6, 0xe1, 0xe0, 0xff, 0xe2, 0xde, 0xdc, 0xff, 0xe0, 0xda, 0xd8, 0xff,
0xdd, 0xd7, 0xd5, 0xff, 0xde, 0xda, 0xd9, 0xff, 0xde, 0xda, 0xda, 0xff,
0xdc, 0xd7, 0xd8, 0xff, 0xdf, 0xdc, 0xdc, 0xff, 0xe5, 0xe3, 0xe4, 0xff,
0xe1, 0xde, 0xde, 0xff, 0xde, 0xdc, 0xdc, 0xff, 0xe9, 0xe7, 0xe8, 0xff,
0xe8, 0xe7, 0xe6, 0xe7, 0xff, 0xff, 0xff, 0x97, 0xff, 0xff, 0xff, 0x93,
0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x88, 0xfe, 0xfe, 0xfa, 0x9b,
0xfc, 0xfb, 0xee, 0xff, 0xfc, 0xfa, 0xed, 0xff, 0xfb, 0xfa, 0xeb, 0xff,
0xfb, 0xf8, 0xeb, 0xff, 0xfb, 0xf7, 0xea, 0xff, 0xfa, 0xf6, 0xe8, 0xff,
0xf8, 0xf6, 0xe6, 0xff, 0xf7, 0xf5, 0xe3, 0xff, 0xf9, 0xf9, 0xf9, 0xff,
0xf7, 0xf6, 0xf7, 0xff, 0xf5, 0xf4, 0xf4, 0xff, 0xf0, 0xee, 0xef, 0xff,
0xe8, 0xe7, 0xe7, 0xff, 0xe7, 0xe4, 0xe3, 0xff, 0xe2, 0xdd, 0xdb, 0xff,
0xdf, 0xd9, 0xd7, 0xff, 0xdc, 0xd6, 0xd4, 0xff, 0xd8, 0xd2, 0xcf, 0xff,
0xd8, 0xd2, 0xd1, 0xff, 0xe0, 0xdc, 0xdc, 0xff, 0xdb, 0xd7, 0xd7, 0xff,
0xdb, 0xd7, 0xd7, 0xff, 0xe7, 0xe5, 0xe5, 0xff, 0xde, 0xda, 0xdb, 0xff,
0xdb, 0xd8, 0xd9, 0xff, 0xe0, 0xde, 0xde, 0xff, 0xed, 0xeb, 0xec, 0xe4,
0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0x8b, 0xff, 0xff, 0xff, 0x87,
0xff, 0xff, 0xff, 0x80, 0xfe, 0xfe, 0xfa, 0x94, 0xfd, 0xfb, 0xee, 0xff,
0xfd, 0xfb, 0xed, 0xff, 0xfc, 0xfb, 0xec, 0xff, 0xfc, 0xfa, 0xea, 0xff,
0xf8, 0xf7, 0xe9, 0xff, 0xf8, 0xf6, 0xe7, 0xff, 0xf7, 0xf7, 0xe5, 0xff,
0xf7, 0xf5, 0xe3, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xf5, 0xf4, 0xf4, 0xff,
0xf2, 0xf2, 0xf2, 0xff, 0xe9, 0xe6, 0xe6, 0xff, 0xe9, 0xe7, 0xe6, 0xff,
0xe9, 0xe7, 0xe7, 0xff, 0xe0, 0xdb, 0xda, 0xff, 0xda, 0xd3, 0xd2, 0xff,
0xd6, 0xd0, 0xce, 0xff, 0xd4, 0xcd, 0xcb, 0xff, 0xd0, 0xc8, 0xc7, 0xff,
0xd7, 0xd2, 0xd1, 0xff, 0xd8, 0xd3, 0xd3, 0xff, 0xd4, 0xd1, 0xd1, 0xff,
0xe6, 0xe3, 0xe2, 0xff, 0xdd, 0xda, 0xda, 0xff, 0xe3, 0xe1, 0xe1, 0xff,
0xe0, 0xde, 0xde, 0xff, 0xe7, 0xe5, 0xe5, 0xe3, 0xff, 0xff, 0xff, 0x88,
0xff, 0xff, 0xff, 0x84, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7b,
0xfe, 0xfe, 0xfb, 0x88, 0xfc, 0xfc, 0xef, 0xff, 0xfb, 0xfc, 0xee, 0xff,
0xfb, 0xfa, 0xeb, 0xff, 0xfa, 0xfa, 0xea, 0xff, 0xf9, 0xf9, 0xe7, 0xff,
0xf7, 0xf7, 0xe6, 0xff, 0xf6, 0xf5, 0xe5, 0xff, 0xf7, 0xf5, 0xe3, 0xff,
0xf8, 0xf7, 0xf7, 0xff, 0xf4, 0xf4, 0xf4, 0xff, 0xf2, 0xf2, 0xf1, 0xff,
0xe8, 0xe6, 0xe6, 0xff, 0xe4, 0xe1, 0xe1, 0xff, 0xdd, 0xda, 0xda, 0xff,
0xe7, 0xe3, 0xe3, 0xff, 0xd6, 0xcf, 0xcd, 0xff, 0xd4, 0xcc, 0xca, 0xff,
0xcf, 0xc7, 0xc5, 0xff, 0xcc, 0xc3, 0xc1, 0xff, 0xd3, 0xce, 0xcc, 0xff,
0xd9, 0xd4, 0xd4, 0xff, 0xda, 0xd6, 0xd6, 0xff, 0xe3, 0xe1, 0xe0, 0xff,
0xdb, 0xd8, 0xd7, 0xff, 0xe4, 0xe2, 0xe2, 0xff, 0xe1, 0xde, 0xdf, 0xff,
0xe3, 0xe1, 0xe1, 0xf0, 0xff, 0xff, 0xff, 0x83, 0xff, 0xff, 0xff, 0x7c,
0xff, 0xff, 0xff, 0x78, 0xff, 0xff, 0xff, 0x73, 0xff, 0xff, 0xff, 0x6f,
0xfb, 0xfc, 0xed, 0xff, 0xfa, 0xfb, 0xed, 0xff, 0xfb, 0xfa, 0xeb, 0xff,
0xfa, 0xf9, 0xe9, 0xff, 0xfa, 0xf9, 0xe7, 0xff, 0xf8, 0xf9, 0xe7, 0xff,
0xf7, 0xf5, 0xe3, 0xff, 0xf7, 0xf4, 0xe1, 0xff, 0xf2, 0xf2, 0xf2, 0xff,
0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xf0, 0xef, 0xff, 0xe5, 0xe3, 0xe3, 0xff,
0xdd, 0xd9, 0xd9, 0xff, 0xdf, 0xdc, 0xdc, 0xff, 0xe6, 0xe3, 0xe3, 0xff,
0xe1, 0xda, 0xdb, 0xff, 0xd2, 0xca, 0xc7, 0xff, 0xca, 0xc2, 0xc0, 0xff,
0xc7, 0xbe, 0xbc, 0xff, 0xc8, 0xc2, 0xc0, 0xff, 0xd2, 0xcf, 0xce, 0xff,
0xd5, 0xcf, 0xd0, 0xff, 0xd5, 0xd1, 0xd1, 0xff, 0xda, 0xd6, 0xd7, 0xff,
0xde, 0xdc, 0xdd, 0xff, 0xde, 0xdd, 0xdc, 0xff, 0xe2, 0xe0, 0xe0, 0xff,
0xff, 0xff, 0xff, 0x7c, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff, 0x70,
0xff, 0xff, 0xff, 0x6c, 0xff, 0xff, 0xff, 0x67, 0xfa, 0xfd, 0xed, 0xf8,
0xf9, 0xfc, 0xeb, 0xff, 0xf9, 0xfb, 0xea, 0xff, 0xf8, 0xf9, 0xe8, 0xff,
0xf7, 0xf9, 0xe6, 0xff, 0xf7, 0xf8, 0xe6, 0xff, 0xf6, 0xf5, 0xe4, 0xff,
0xf6, 0xf4, 0xe1, 0xff, 0xe7, 0xe7, 0xe7, 0xff, 0xe3, 0xe4, 0xe3, 0xff,
0xe1, 0xe2, 0xe2, 0xff, 0xe4, 0xe4, 0xe4, 0xff, 0xd7, 0xd6, 0xd5, 0xff,
0xd5, 0xd4, 0xd4, 0xff, 0xdd, 0xdc, 0xdc, 0xff, 0xdc, 0xda, 0xda, 0xff,
0xd0, 0xc9, 0xc9, 0xff, 0xc9, 0xbf, 0xbe, 0xff, 0xc2, 0xba, 0xb8, 0xff,
0xc0, 0xb8, 0xb6, 0xff, 0xcc, 0xc7, 0xc7, 0xff, 0xd2, 0xcd, 0xcd, 0xff,
0xd2, 0xce, 0xcf, 0xff, 0xd1, 0xcc, 0xcd, 0xff, 0xdf, 0xde, 0xde, 0xff,
0xe7, 0xe6, 0xe6, 0xff, 0xe4, 0xe3, 0xe3, 0xff, 0xfd, 0xfd, 0xfd, 0x78,
0xff, 0xff, 0xff, 0x70, 0xff, 0xff, 0xff, 0x6b, 0xff, 0xff, 0xff, 0x67,
0xff, 0xff, 0xff, 0x60, 0xfc, 0xfe, 0xef, 0xcf, 0xf9, 0xfc, 0xec, 0xff,
0xfa, 0xfa, 0xe9, 0xff, 0xf8, 0xfa, 0xe8, 0xff, 0xf7, 0xf7, 0xe5, 0xff,
0xf6, 0xf7, 0xe5, 0xff, 0xf5, 0xf5, 0xe3, 0xff, 0xf6, 0xf4, 0xe0, 0xff,
0xdc, 0xdd, 0xdd, 0xff, 0xdb, 0xdc, 0xdc, 0xff, 0xd3, 0xd4, 0xd4, 0xff,
0xd8, 0xd8, 0xd8, 0xff, 0xd1, 0xd1, 0xd1, 0xff, 0xd0, 0xd0, 0xd0, 0xff,
0xca, 0xcb, 0xcb, 0xff, 0xcc, 0xcc, 0xcd, 0xff, 0xcb, 0xcb, 0xcb, 0xff,
0xc6, 0xc1, 0xc1, 0xff, 0xc0, 0xbc, 0xba, 0xff, 0xba, 0xb1, 0xaf, 0xff,
0xc5, 0xbf, 0xc0, 0xff, 0xd6, 0xd2, 0xd2, 0xff, 0xc4, 0xbf, 0xbf, 0xff,
0xd3, 0xce, 0xcd, 0xff, 0xd3, 0xd1, 0xd2, 0xff, 0xe3, 0xe2, 0xe2, 0xff,
0xe6, 0xe4, 0xe4, 0xff, 0xee, 0xee, 0xed, 0x9b, 0xff, 0xff, 0xff, 0x68,
0xff, 0xff, 0xff, 0x63, 0xff, 0xff, 0xff, 0x5f, 0xff, 0xff, 0xff, 0x5b,
0xfd, 0xfe, 0xf6, 0x80, 0xf9, 0xfc, 0xeb, 0xff, 0xf7, 0xfa, 0xeb, 0xff,
0xf7, 0xf9, 0xe9, 0xff, 0xf6, 0xf8, 0xe8, 0xff, 0xf6, 0xf7, 0xe5, 0xff,
0xf5, 0xf4, 0xe4, 0xff, 0xf5, 0xf4, 0xe3, 0xff, 0xd7, 0xd8, 0xd8, 0xff,
0xd4, 0xd5, 0xd4, 0xff, 0xd2, 0xd3, 0xd3, 0xff, 0xcf, 0xd0, 0xd0, 0xff,
0xcc, 0xce, 0xcd, 0xff, 0xc9, 0xca, 0xca, 0xff, 0xc5, 0xc6, 0xc6, 0xff,
0xc3, 0xc4, 0xc4, 0xff, 0xbf, 0xbf, 0xbd, 0xff, 0xbe, 0xbf, 0xbf, 0xff,
0xba, 0xba, 0xba, 0xff, 0xb4, 0xb1, 0xb1, 0xff, 0xbb, 0xba, 0xb9, 0xff,
0xc9, 0xc8, 0xc7, 0xff, 0xe2, 0xde, 0xde, 0xff, 0xc1, 0xbd, 0xbd, 0xff,
0xd6, 0xd5, 0xd5, 0xff, 0xde, 0xdd, 0xdc, 0xff, 0xdc, 0xda, 0xda, 0xff,
0xe6, 0xe5, 0xe5, 0xcf, 0xff, 0xff, 0xff, 0x63, 0xff, 0xff, 0xff, 0x5c,
0xff, 0xff, 0xff, 0x58, 0xff, 0xff, 0xff, 0x53, 0xff, 0xff, 0xff, 0x4f,
0xf9, 0xfc, 0xeb, 0xfb, 0xf6, 0xf9, 0xeb, 0xff, 0xf6, 0xf9, 0xea, 0xff,
0xf6, 0xf9, 0xe8, 0xff, 0xf5, 0xf5, 0xe4, 0xff, 0xf6, 0xf6, 0xe4, 0xff,
0xf5, 0xf4, 0xe2, 0xff, 0xd3, 0xd4, 0xd4, 0xff, 0xcc, 0xcd, 0xcd, 0xff,
0xce, 0xcf, 0xcf, 0xff, 0xc9, 0xcb, 0xcb, 0xff, 0xc6, 0xc7, 0xc7, 0xff,
0xc3, 0xc5, 0xc4, 0xff, 0xc0, 0xc1, 0xc1, 0xff, 0xbb, 0xbd, 0xbc, 0xff,
0xb7, 0xb9, 0xb8, 0xff, 0xb6, 0xb7, 0xb7, 0xff, 0xb4, 0xb7, 0xb6, 0xff,
0xaf, 0xaf, 0xaf, 0xff, 0xb0, 0xb2, 0xb2, 0xff, 0xb5, 0xb5, 0xb5, 0xff,
0xc1, 0xc0, 0xc0, 0xff, 0xc9, 0xc6, 0xc7, 0xff, 0xb3, 0xad, 0xae, 0xff,
0xcf, 0xcd, 0xce, 0xff, 0xe3, 0xe2, 0xe2, 0xff, 0xe4, 0xe2, 0xe2, 0xff,
0xfd, 0xfd, 0xfd, 0x60, 0xff, 0xff, 0xff, 0x57, 0xff, 0xff, 0xff, 0x50,
0xff, 0xff, 0xff, 0x4c, 0xff, 0xff, 0xff, 0x47, 0xfa, 0xfb, 0xef, 0xa8,
0xf8, 0xfc, 0xed, 0xff, 0xf7, 0xf9, 0xea, 0xff, 0xf6, 0xf7, 0xe7, 0xff,
0xf6, 0xf4, 0xe7, 0xff, 0xf5, 0xf4, 0xe5, 0xff, 0xf4, 0xf3, 0xe3, 0xff,
0xce, 0xcf, 0xcf, 0xff, 0xc8, 0xc9, 0xc9, 0xff, 0xc6, 0xc8, 0xc8, 0xff,
0xc4, 0xc6, 0xc6, 0xff, 0xc2, 0xc3, 0xc3, 0xff, 0xba, 0xbd, 0xbc, 0xff,
0xbc, 0xbe, 0xbe, 0xff, 0xb5, 0xb8, 0xb7, 0xff, 0xb4, 0xb6, 0xb5, 0xff,
0xb0, 0xb2, 0xb2, 0xff, 0xaf, 0xb1, 0xb0, 0xff, 0xaa, 0xad, 0xac, 0xff,
0xaa, 0xad, 0xac, 0xff, 0xa7, 0xa9, 0xa8, 0xff, 0xa4, 0xa5, 0xa5, 0xff,
0xa7, 0xa8, 0xa8, 0xff, 0xc4, 0xc3, 0xc3, 0xff, 0xb8, 0xb7, 0xb7, 0xff,
0xc0, 0xbf, 0xbe, 0xff, 0xd0, 0xce, 0xce, 0xff, 0xe3, 0xe2, 0xe2, 0x94,
0xff, 0xff, 0xff, 0x4f, 0xff, 0xff, 0xff, 0x4b, 0xff, 0xff, 0xff, 0x44,
0xff, 0xff, 0xff, 0x40, 0xed, 0xe7, 0xe6, 0x48, 0xba, 0xad, 0xa1, 0xff,
0xd6, 0xcf, 0xc1, 0xff, 0xf4, 0xf3, 0xe4, 0xff, 0xf5, 0xf4, 0xe5, 0xff,
0xf5, 0xf3, 0xe5, 0xff, 0xf5, 0xf5, 0xe5, 0xff, 0xc7, 0xc9, 0xc8, 0xff,
0xc5, 0xc6, 0xc6, 0xff, 0xc1, 0xc2, 0xc2, 0xff, 0xbd, 0xbe, 0xbe, 0xff,
0xba, 0xbc, 0xbb, 0xff, 0xb3, 0xb4, 0xb4, 0xff, 0xb2, 0xb5, 0xb4, 0xff,
0xb1, 0xb4, 0xb3, 0xff, 0xac, 0xaf, 0xae, 0xff, 0xa8, 0xaa, 0xa9, 0xff,
0xa8, 0xab, 0xaa, 0xff, 0xa1, 0xa4, 0xa3, 0xff, 0xa1, 0xa4, 0xa3, 0xff,
0xa3, 0xa5, 0xa4, 0xff, 0x9f, 0xa1, 0xa0, 0xff, 0x99, 0x9b, 0x9a, 0xff,
0x98, 0x9a, 0x9a, 0xff, 0x97, 0x9a, 0x99, 0xff, 0xa0, 0xa0, 0xa0, 0xff,
0x9b, 0x9b, 0x9b, 0xff, 0x9f, 0xa0, 0x9f, 0xe8, 0xff, 0xff, 0xff, 0x48,
0xff, 0xff, 0xff, 0x44, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0x3b,
0xff, 0xff, 0xff, 0x34, 0xbb, 0xa7, 0xa5, 0xd8, 0xb9, 0xa9, 0xa6, 0xff,
0xb9, 0xac, 0xa0, 0xff, 0xf8, 0xfa, 0xe7, 0xff, 0xf5, 0xf4, 0xe6, 0xff,
0xf4, 0xf3, 0xe4, 0xff, 0xc0, 0xc0, 0xbf, 0xff, 0xbb, 0xbb, 0xbb, 0xff,
0xbb, 0xbc, 0xbb, 0xff, 0xb6, 0xb6, 0xb6, 0xff, 0xb0, 0xb1, 0xb1, 0xff,
0xad, 0xad, 0xad, 0xff, 0xa8, 0xa7, 0xa7, 0xff, 0xa8, 0xa9, 0xa9, 0xff,
0xa5, 0xa6, 0xa6, 0xff, 0xa4, 0xa6, 0xa5, 0xff, 0xa3, 0xa6, 0xa6, 0xff,
0x9b, 0x9d, 0x9c, 0xff, 0x96, 0x99, 0x99, 0xff, 0x9b, 0x9d, 0x9d, 0xff,
0x97, 0x99, 0x98, 0xff, 0x8e, 0x91, 0x91, 0xff, 0x98, 0x9b, 0x9b, 0xff,
0x89, 0x8c, 0x8b, 0xff, 0x87, 0x8b, 0x89, 0xff, 0x84, 0x7f, 0x81, 0xff,
0x82, 0x82, 0x83, 0xff, 0xc0, 0xbe, 0xbf, 0x67, 0xff, 0xff, 0xff, 0x3c,
0xff, 0xff, 0xff, 0x37, 0xff, 0xff, 0xff, 0x33, 0xff, 0xff, 0xff, 0x2f,
0xc6, 0xbb, 0xb9, 0x50, 0xac, 0x9c, 0x99, 0xff, 0xa8, 0x98, 0x91, 0xff,
0xbd, 0xb0, 0xa5, 0xff, 0xf6, 0xf5, 0xe6, 0xff, 0xf4, 0xf3, 0xe4, 0xff,
0xbb, 0xbb, 0xba, 0xff, 0xb3, 0xb3, 0xb3, 0xff, 0xb3, 0xb4, 0xb4, 0xff,
0xae, 0xaf, 0xae, 0xff, 0xad, 0xae, 0xae, 0xff, 0xb2, 0xb4, 0xb4, 0xfc,
0xa8, 0xa8, 0xa9, 0xf3, 0xa7, 0xa7, 0xa7, 0xf3, 0x9e, 0x9f, 0x9d, 0xfc,
0x9b, 0x9c, 0x9a, 0xff, 0x9c, 0x9e, 0x9e, 0xff, 0x94, 0x96, 0x94, 0xff,
0x90, 0x90, 0x90, 0xff, 0x96, 0x98, 0x99, 0xff, 0x8d, 0x8f, 0x8e, 0xff,
0x83, 0x83, 0x84, 0xff, 0x8f, 0x92, 0x91, 0xff, 0x83, 0x85, 0x85, 0xff,
0x87, 0x87, 0x87, 0xff, 0x7c, 0x7d, 0x7d, 0xff, 0x78, 0x74, 0x72, 0xff,
0x95, 0x93, 0x92, 0x97, 0xff, 0xff, 0xff, 0x34, 0xff, 0xff, 0xff, 0x30,
0xff, 0xff, 0xff, 0x2c, 0xff, 0xff, 0xff, 0x27, 0xff, 0xff, 0xff, 0x23,
0xa2, 0x93, 0x94, 0xe7, 0x96, 0x83, 0x81, 0xff, 0xa8, 0x91, 0x8b, 0xff,
0xc4, 0xbc, 0xb2, 0xff, 0xf5, 0xf5, 0xe4, 0xff, 0xb7, 0xb9, 0xb8, 0xff,
0xaf, 0xaf, 0xae, 0xff, 0xaf, 0xaf, 0xaf, 0xff, 0xac, 0xad, 0xae, 0xff,
0xa8, 0xaa, 0xa9, 0xff, 0xae, 0xaf, 0xaf, 0xec, 0xc6, 0xc7, 0xc7, 0xb4,
0xc5, 0xc6, 0xc6, 0xb3, 0x9a, 0x99, 0x99, 0xeb, 0x91, 0x91, 0x90, 0xff,
0x94, 0x95, 0x95, 0xff, 0x95, 0x96, 0x96, 0xff, 0x8c, 0x8e, 0x8e, 0xff,
0x86, 0x88, 0x87, 0xff, 0x83, 0x82, 0x82, 0xff, 0x80, 0x81, 0x81, 0xff,
0x82, 0x84, 0x84, 0xff, 0x7b, 0x79, 0x7a, 0xff, 0x73, 0x74, 0x73, 0xff,
0x79, 0x7a, 0x7b, 0xff, 0x75, 0x73, 0x72, 0xff, 0x6f, 0x70, 0x6e, 0xfc,
0xe8, 0xe7, 0xe7, 0x37, 0xff, 0xff, 0xff, 0x2b, 0xff, 0xff, 0xff, 0x24,
0xff, 0xff, 0xff, 0x20, 0xff, 0xff, 0xff, 0x1c, 0x70, 0x6e, 0x6d, 0xeb,
0x6c, 0x69, 0x66, 0xff, 0x83, 0x78, 0x7b, 0xff, 0x83, 0x7f, 0x78, 0xff,
0xdc, 0xd5, 0xcd, 0xff, 0xb3, 0xb5, 0xb4, 0xff, 0xa9, 0xa9, 0xaa, 0xff,
0xa7, 0xa8, 0xa7, 0xff, 0xa7, 0xa8, 0xa7, 0xff, 0xa6, 0xa8, 0xa8, 0xff,
0xab, 0xac, 0xab, 0xe3, 0xdb, 0xdc, 0xdc, 0x97, 0xd9, 0xda, 0xda, 0x93,
0x99, 0x99, 0x98, 0xe0, 0x94, 0x95, 0x95, 0xff, 0x8e, 0x8f, 0x8e, 0xff,
0x8f, 0x93, 0x92, 0xff, 0x88, 0x8a, 0x89, 0xff, 0x79, 0x78, 0x78, 0xff,
0x80, 0x82, 0x82, 0xff, 0x7f, 0x81, 0x81, 0xff, 0x7f, 0x7d, 0x7e, 0xff,
0x76, 0x72, 0x72, 0xff, 0x70, 0x70, 0x70, 0xff, 0x73, 0x73, 0x73, 0xff,
0x67, 0x66, 0x64, 0xff, 0x6b, 0x6b, 0x6a, 0xff, 0x70, 0x73, 0x72, 0xd4,
0xff, 0xff, 0xff, 0x23, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x1b,
0x79, 0x74, 0x72, 0x67, 0x63, 0x61, 0x61, 0xff, 0x63, 0x62, 0x60, 0xff,
0x5e, 0x5c, 0x5a, 0xff, 0x61, 0x5f, 0x5c, 0xff, 0x6b, 0x63, 0x5e, 0xff,
0xae, 0xaf, 0xaf, 0xff, 0xa9, 0xa9, 0xa9, 0xff, 0x9c, 0x9b, 0x99, 0xff,
0x9d, 0x9c, 0x9b, 0xff, 0x9c, 0x9c, 0x9c, 0xff, 0x9c, 0x9c, 0x9d, 0xf7,
0xaa, 0xac, 0xac, 0xd4, 0xa5, 0xa7, 0xa6, 0xd3, 0x98, 0x9a, 0x9a, 0xf4,
0x8d, 0x8e, 0x8e, 0xff, 0x85, 0x85, 0x85, 0xff, 0x85, 0x86, 0x86, 0xff,
0x82, 0x84, 0x84, 0xff, 0x7b, 0x7b, 0x7b, 0xff, 0x7e, 0x82, 0x81, 0xff,
0x79, 0x7b, 0x7b, 0xff, 0x79, 0x7b, 0x7b, 0xff, 0x72, 0x73, 0x73, 0xff,
0x70, 0x6e, 0x6e, 0xff, 0x6d, 0x6d, 0x6d, 0xff, 0x61, 0x5f, 0x5d, 0xff,
0x5d, 0x5d, 0x5b, 0xff, 0x64, 0x60, 0x61, 0xff, 0x5e, 0x5d, 0x5d, 0xec,
0x6a, 0x69, 0x67, 0xa0, 0x67, 0x66, 0x64, 0xbc, 0x59, 0x56, 0x55, 0xff,
0x54, 0x51, 0x4e, 0xff, 0x56, 0x52, 0x51, 0xff, 0x55, 0x52, 0x4f, 0xff,
0x52, 0x4e, 0x49, 0xff, 0x54, 0x54, 0x52, 0xff, 0xa9, 0xac, 0xab, 0xff,
0xa1, 0xa0, 0xa0, 0xff, 0x9a, 0x99, 0x98, 0xff, 0x97, 0x97, 0x96, 0xff,
0x95, 0x94, 0x94, 0xff, 0x8e, 0x8c, 0x8c, 0xff, 0x95, 0x98, 0x97, 0xfc,
0x90, 0x91, 0x91, 0xfc, 0x95, 0x96, 0x96, 0xff, 0x86, 0x86, 0x86, 0xff,
0x81, 0x82, 0x80, 0xff, 0x7d, 0x7e, 0x7b, 0xff, 0x78, 0x79, 0x78, 0xff,
0x71, 0x70, 0x6e, 0xff, 0x72, 0x71, 0x70, 0xff, 0x72, 0x73, 0x72, 0xff,
0x70, 0x70, 0x6e, 0xff, 0x6d, 0x6a, 0x6a, 0xff, 0x64, 0x64, 0x63, 0xff,
0x69, 0x68, 0x67, 0xff, 0x61, 0x5f, 0x5e, 0xff, 0x59, 0x57, 0x57, 0xff,
0x5f, 0x5f, 0x5e, 0xff, 0x55, 0x55, 0x53, 0xff, 0x57, 0x58, 0x57, 0xff,
0x51, 0x53, 0x50, 0xff, 0x54, 0x51, 0x51, 0xff, 0x4c, 0x4b, 0x4a, 0xff,
0x49, 0x4a, 0x47, 0xff, 0x4f, 0x51, 0x4e, 0xff, 0x4f, 0x4d, 0x49, 0xff,
0x4c, 0x4b, 0x46, 0xff, 0xa7, 0xaa, 0xaa, 0xff, 0x99, 0x98, 0x98, 0xff,
0x95, 0x92, 0x92, 0xff, 0x94, 0x93, 0x92, 0xff, 0x8a, 0x87, 0x84, 0xff,
0x85, 0x80, 0x7f, 0xff, 0x8d, 0x90, 0x8f, 0xff, 0x85, 0x85, 0x85, 0xff,
0x8e, 0x8e, 0x8e, 0xff, 0x80, 0x80, 0x81, 0xff, 0x7c, 0x7d, 0x7b, 0xff,
0x79, 0x79, 0x78, 0xff, 0x78, 0x79, 0x78, 0xff, 0x6e, 0x6c, 0x6b, 0xff,
0x68, 0x66, 0x66, 0xff, 0x69, 0x6a, 0x67, 0xff, 0x60, 0x5e, 0x5d, 0xff,
0x5b, 0x58, 0x57, 0xff, 0x58, 0x56, 0x55, 0xff, 0x61, 0x5e, 0x5d, 0xff,
0x54, 0x53, 0x52, 0xff, 0x60, 0x5d, 0x5c, 0xff, 0x5b, 0x5b, 0x5a, 0xff,
0x59, 0x5a, 0x58, 0xff, 0x48, 0x43, 0x42, 0xff, 0x44, 0x40, 0x40, 0xff,
0x48, 0x46, 0x44, 0xff, 0x4a, 0x46, 0x46, 0xff, 0x4c, 0x4f, 0x4c, 0xff,
0x49, 0x4a, 0x48, 0xff, 0x47, 0x46, 0x41, 0xff, 0x44, 0x43, 0x3f, 0xff,
0xa2, 0xa4, 0xa4, 0xff, 0x96, 0x95, 0x96, 0xff, 0x8e, 0x8c, 0x8a, 0xff,
0x89, 0x86, 0x86, 0xff, 0x82, 0x7c, 0x7c, 0xff, 0x83, 0x80, 0x7f, 0xff,
0x82, 0x82, 0x80, 0xff, 0x82, 0x83, 0x81, 0xff, 0x82, 0x85, 0x85, 0xff,
0x7c, 0x7c, 0x7c, 0xff, 0x77, 0x78, 0x75, 0xff, 0x75, 0x77, 0x76, 0xff,
0x71, 0x72, 0x70, 0xff, 0x68, 0x66, 0x65, 0xff, 0x62, 0x60, 0x5f, 0xff,
0x5f, 0x5e, 0x5c, 0xff, 0x5a, 0x52, 0x4f, 0xff, 0x5b, 0x53, 0x4f, 0xff,
0x50, 0x49, 0x49, 0xff, 0x5c, 0x58, 0x57, 0xff, 0x50, 0x4b, 0x49, 0xff,
0x57, 0x54, 0x53, 0xff, 0x4f, 0x4f, 0x4e, 0xff, 0x53, 0x57, 0x55, 0xff,
0x48, 0x45, 0x44, 0xff, 0x3c, 0x33, 0x33, 0xff, 0x49, 0x45, 0x43, 0xff,
0x41, 0x3f, 0x3d, 0xff, 0x49, 0x46, 0x44, 0xff, 0x4a, 0x48, 0x47, 0xff,
0x3f, 0x3c, 0x3a, 0xff, 0x43, 0x41, 0x3e, 0xff, 0x99, 0x9c, 0x9a, 0xff,
0x90, 0x8e, 0x8f, 0xff, 0x8c, 0x8b, 0x89, 0xff, 0x81, 0x7c, 0x7c, 0xff,
0x7d, 0x78, 0x78, 0xff, 0x82, 0x82, 0x80, 0xff, 0x77, 0x74, 0x73, 0xff,
0x75, 0x73, 0x73, 0xff, 0x78, 0x76, 0x76, 0xff, 0x70, 0x6f, 0x6f, 0xff,
0x6d, 0x6c, 0x6b, 0xff, 0x6e, 0x6f, 0x6d, 0xff, 0x68, 0x68, 0x66, 0xff,
0x5f, 0x5b, 0x5b, 0xff, 0x5b, 0x56, 0x56, 0xff, 0x5a, 0x58, 0x57, 0xff,
0x53, 0x49, 0x47, 0xff, 0x4e, 0x45, 0x43, 0xff, 0x49, 0x43, 0x41, 0xff,
0x5f, 0x5b, 0x5a, 0xff, 0x46, 0x3f, 0x3e, 0xff, 0x4b, 0x48, 0x47, 0xff,
0x42, 0x3f, 0x3f, 0xff, 0x4d, 0x50, 0x50, 0xff, 0x52, 0x52, 0x51, 0xff,
0x37, 0x31, 0x30, 0xff, 0x3d, 0x38, 0x37, 0xff, 0x3f, 0x39, 0x38, 0xff,
0x40, 0x3c, 0x3b, 0xff, 0x4a, 0x48, 0x47, 0xff, 0x3f, 0x3d, 0x3b, 0xff,
0x46, 0x45, 0x43, 0xff,
};
#endif // WEBP_TESTS_FUZZER_IMG_ALPHA_H_
+115
View File
@@ -0,0 +1,115 @@
// Copyright 2018 Google Inc.
//
// 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.
//
////////////////////////////////////////////////////////////////////////////////
#ifndef WEBP_TESTS_FUZZER_IMG_GRID_H_
#define WEBP_TESTS_FUZZER_IMG_GRID_H_
#include <stdint.h>
static const int kImgGridWidth = 16;
static const int kImgGridHeight = 16;
/*Pixel format: Red: 8 bit, Green: 8 bit, Blue: 8 bit, Fix 0xFF: 8 bit*/
static const uint8_t kImgGridData[] = {
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff,
};
#endif // WEBP_TESTS_FUZZER_IMG_GRID_H_
File diff suppressed because it is too large Load Diff
+145
View File
@@ -0,0 +1,145 @@
// Copyright 2018 Google Inc.
//
// 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 <array>
#include <cstddef>
#include <cstdint>
#include <string_view>
#include "./fuzz_utils.h"
#include "webp/demux.h"
#include "webp/mux.h"
#include "webp/mux_types.h"
namespace {
void MuxDemuxApiTest(std::string_view data_in, bool use_mux_api,
const std::array<int, 10>& chunk_flags) {
const size_t size = data_in.size();
WebPData webp_data;
WebPDataInit(&webp_data);
webp_data.size = size;
webp_data.bytes = reinterpret_cast<const uint8_t*>(data_in.data());
// Extracted chunks and frames are not processed or decoded,
// which is already covered extensively by the other fuzz targets.
if (use_mux_api) {
// Mux API
WebPMux* mux = WebPMuxCreate(&webp_data, size & 2);
if (!mux) return;
WebPData chunk;
(void)WebPMuxGetChunk(mux, "EXIF", &chunk);
(void)WebPMuxGetChunk(mux, "ICCP", &chunk);
(void)WebPMuxGetChunk(mux, "FUZZ", &chunk); // unknown
uint32_t flags;
(void)WebPMuxGetFeatures(mux, &flags);
int width = 0, height = 0;
(void)WebPMuxGetCanvasSize(mux, &width, &height);
WebPMuxAnimParams params;
(void)WebPMuxGetAnimationParams(mux, &params);
WebPMuxError status;
WebPMuxFrameInfo info;
for (int i = 0; i < fuzz_utils::kFuzzFrameLimit; i++) {
status = WebPMuxGetFrame(mux, i + 1, &info);
if (status == WEBP_MUX_NOT_FOUND) {
break;
} else if (status == WEBP_MUX_OK) {
WebPDataClear(&info.bitstream);
}
}
// Try setting a custom chunk.
if (size > 20) {
WebPData custom_chunk;
custom_chunk.bytes = reinterpret_cast<const uint8_t*>(data_in.data()) + 4;
custom_chunk.size = size - 4;
int chunk_idx = 0;
for (std::string_view fourcc : {"VP8X", "ICCP", "ANIM", "EXIF", "XMP ",
"ANMF", "ALPH", "VP8 ", "VP8L", "FUZZ"}) {
// The last five image chunks should return WEBP_MUX_INVALID_ARGUMENT.
for (int i = 0; i < chunk_flags[chunk_idx]; i++) {
(void)WebPMuxSetChunk(mux, fourcc.data(), &custom_chunk, 0);
}
chunk_idx++;
}
}
// Try assembling the mux
WebPData assembled;
WebPDataInit(&assembled);
(void)WebPMuxAssemble(mux, &assembled);
WebPDataClear(&assembled);
// Get number of chunks of various types
for (int chunk_type = WEBP_CHUNK_VP8X; chunk_type <= WEBP_CHUNK_NIL;
++chunk_type) {
int num_chunks = 0;
(void)WebPMuxNumChunks(mux, static_cast<WebPChunkId>(chunk_type),
&num_chunks);
}
WebPMuxDelete(mux);
} else {
// Demux API
WebPDemuxer* demux;
if (size & 2) {
WebPDemuxState state;
demux = WebPDemuxPartial(&webp_data, &state);
if (state < WEBP_DEMUX_PARSED_HEADER) {
WebPDemuxDelete(demux);
return;
}
} else {
demux = WebPDemux(&webp_data);
if (!demux) return;
}
WebPChunkIterator chunk_iter;
if (WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter)) {
(void)WebPDemuxNextChunk(&chunk_iter);
}
WebPDemuxReleaseChunkIterator(&chunk_iter);
if (WebPDemuxGetChunk(demux, "ICCP", 0, &chunk_iter)) { // 0 == last
(void)WebPDemuxPrevChunk(&chunk_iter);
}
WebPDemuxReleaseChunkIterator(&chunk_iter);
// Skips FUZZ because the Demux API has no concept of (un)known chunks.
WebPIterator iter;
if (WebPDemuxGetFrame(demux, 1, &iter)) {
for (int i = 1; i < fuzz_utils::kFuzzFrameLimit; i++) {
if (!WebPDemuxNextFrame(&iter)) break;
}
}
WebPDemuxReleaseIterator(&iter);
WebPDemuxDelete(demux);
}
}
} // namespace
FUZZ_TEST(MuxDemuxApi, MuxDemuxApiTest)
.WithDomains(
fuzztest::String().WithMaxSize(fuzz_utils::kMaxWebPFileSize + 1),
/*mux=*/fuzztest::Arbitrary<bool>(),
/*chunk_flags=*/fuzztest::ArrayOf<10>(fuzztest::InRange(0, 2)));
+337
View File
@@ -0,0 +1,337 @@
/*
MIT License
Copyright (c) 2025 Catena cyber
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef WEBP_TESTS_FUZZER_NALLOC_H_
#define WEBP_TESTS_FUZZER_NALLOC_H_
#if defined(WEBP_FUZZER_ENABLE_NALLOC)
#if defined(__clang__) && defined(__has_feature)
#if __has_feature(address_sanitizer)
#define NALLOC_ASAN 1
#endif
#endif
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
static const uint32_t nalloc_crc32_table[] = {
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4};
// Nallocfuzz data to take a decision
uint32_t nalloc_random_state = 0;
__thread unsigned int nalloc_running = 0;
bool nalloc_initialized = false;
uint32_t nalloc_runs = 0;
// Nalloc fuzz parameters
uint32_t nalloc_bitmask = 0xFF;
bool nalloc_random_bitmask = true;
uint32_t nalloc_magic = 0x294cee63;
bool nalloc_verbose = false;
#ifdef NALLOC_ASAN
extern void __sanitizer_print_stack_trace(void);
#endif
// Generic init, using env variables to get parameters
void nalloc_init(const char* prog) {
if (nalloc_initialized) {
return;
}
nalloc_initialized = true;
char* bitmask = getenv("NALLOC_FREQ");
if (bitmask) {
int shift = atoi(bitmask);
if (shift > 0 && shift < 31) {
nalloc_bitmask = 1 << shift;
nalloc_random_bitmask = false;
} else if (shift == 0) {
nalloc_random_bitmask = false;
nalloc_bitmask = 0;
}
} else if (prog == NULL || strstr(prog, "nalloc") == NULL) {
nalloc_random_bitmask = false;
nalloc_bitmask = 0;
return;
}
char* magic = getenv("NALLOC_MAGIC");
if (magic) {
nalloc_magic = (uint32_t)strtol(magic, NULL, 0);
}
char* verbose = getenv("NALLOC_VERBOSE");
if (verbose) {
nalloc_verbose = true;
}
}
// add one byte to the CRC
static inline void nalloc_random_update(uint8_t b) {
nalloc_random_state =
((uint32_t)((uint32_t)nalloc_random_state << 8)) ^
nalloc_crc32_table[((nalloc_random_state >> 24) ^ b) & 0xFF];
}
// Start the failure injections, using a buffer as seed
static int nalloc_start(const uint8_t* data, size_t size) {
if (nalloc_random_bitmask) {
if (nalloc_random_state & 0x10) {
nalloc_bitmask = 0xFFFFFFFF;
} else {
nalloc_bitmask = 1 << (5 + (nalloc_random_state & 0xF));
}
} else if (nalloc_bitmask == 0) {
// nalloc disabled
return 0;
}
nalloc_random_state = 0;
for (size_t i = 0; i < size; i++) {
nalloc_random_update(data[i]);
}
if (__sync_fetch_and_add(&nalloc_running, 1)) {
__sync_fetch_and_sub(&nalloc_running, 1);
return 0;
}
nalloc_runs++;
return 1;
}
// Stop the failure injections
static void nalloc_end() { __sync_fetch_and_sub(&nalloc_running, 1); }
static bool nalloc_backtrace_exclude(size_t size, const char* op) {
if (nalloc_verbose) {
fprintf(stderr, "failed %s(%zu) \n", op, size);
#ifdef NALLOC_ASAN
__sanitizer_print_stack_trace();
#endif
}
return false;
}
//
static bool nalloc_fail(size_t size, const char* op) {
// do not fail before thread init
if (nalloc_runs == 0) {
return false;
}
if (__sync_fetch_and_add(&nalloc_running, 1) != 1) {
// do not fail allocations outside of fuzzer input
// and do not fail inside of this function
__sync_fetch_and_sub(&nalloc_running, 1);
return false;
}
nalloc_random_update((uint8_t)size);
if (size >= 0x100) {
nalloc_random_update((uint8_t)(size >> 8));
if (size >= 0x10000) {
nalloc_random_update((uint8_t)(size >> 16));
// bigger may already fail or oom
}
}
if (((nalloc_random_state ^ nalloc_magic) & nalloc_bitmask) == 0) {
if (nalloc_backtrace_exclude(size, op)) {
__sync_fetch_and_sub(&nalloc_running, 1);
return false;
}
__sync_fetch_and_sub(&nalloc_running, 1);
return true;
}
__sync_fetch_and_sub(&nalloc_running, 1);
return false;
}
// ASAN interceptor for libc routines
#ifdef NALLOC_ASAN
extern void* __interceptor_malloc(size_t);
extern void* __interceptor_calloc(size_t, size_t);
extern void* __interceptor_realloc(void*, size_t);
extern void* __interceptor_reallocarray(void*, size_t, size_t);
extern ssize_t __interceptor_read(int, void*, size_t);
extern ssize_t __interceptor_write(int, const void*, size_t);
extern ssize_t __interceptor_recv(int, void*, size_t, int);
extern ssize_t __interceptor_send(int, const void*, size_t, int);
#define nalloc_malloc(s) __interceptor_malloc(s)
#define nalloc_calloc(s, n) __interceptor_calloc(s, n)
#define nalloc_realloc(p, s) __interceptor_realloc(p, s)
#define nalloc_reallocarray(p, s, n) __interceptor_reallocarray(p, s, n)
#define nalloc_read(f, b, s) __interceptor_read(f, b, s)
#define nalloc_write(f, b, s) __interceptor_write(f, b, s)
#define nalloc_recv(f, b, s, x) __interceptor_recv(f, b, s, x)
#define nalloc_send(f, b, s, x) __interceptor_send(f, b, s, x)
#else
extern void* __libc_malloc(size_t);
extern void* __libc_calloc(size_t, size_t);
extern void* __libc_realloc(void*, size_t);
extern void* __libc_reallocarray(void*, size_t, size_t);
extern ssize_t __read(int, void*, size_t);
extern ssize_t __write(int, const void*, size_t);
extern ssize_t __recv(int, void*, size_t, int);
extern ssize_t __send(int, const void*, size_t, int);
#define nalloc_malloc(s) __libc_malloc(s)
#define nalloc_calloc(s, n) __libc_calloc(s, n)
#define nalloc_realloc(p, s) __libc_realloc(p, s)
#define nalloc_reallocarray(p, s, n) __libc_reallocarray(p, s, n)
#define nalloc_read(f, b, s) __read(f, b, s)
#define nalloc_write(f, b, s) __write(f, b, s)
#define nalloc_recv(f, b, s, x) __recv(f, b, s, x)
#define nalloc_send(f, b, s, x) __send(f, b, s, x)
#endif
// nalloc standard function overwrites with pseudo-random failures
ssize_t read(int fd, void* buf, size_t count) {
if (nalloc_fail(count, "read")) {
errno = EIO;
return -1;
}
return nalloc_read(fd, buf, count);
}
ssize_t write(int fd, const void* buf, size_t count) {
if (nalloc_fail(count, "write")) {
errno = EIO;
return -1;
}
return nalloc_write(fd, buf, count);
}
ssize_t recv(int fd, void* buf, size_t count, int flags) {
if (nalloc_fail(count, "recv")) {
errno = EIO;
return -1;
}
return nalloc_recv(fd, buf, count, flags);
}
ssize_t send(int fd, const void* buf, size_t count, int flags) {
if (nalloc_fail(count, "send")) {
errno = EIO;
return -1;
}
return nalloc_send(fd, buf, count, flags);
}
void* calloc(size_t nmemb, size_t size) {
if (nalloc_fail(size, "calloc")) {
errno = ENOMEM;
return NULL;
}
return nalloc_calloc(nmemb, size);
}
void* malloc(size_t size) {
if (nalloc_fail(size, "malloc")) {
errno = ENOMEM;
return NULL;
}
return nalloc_malloc(size);
}
void* realloc(void* ptr, size_t size) {
if (nalloc_fail(size, "realloc")) {
errno = ENOMEM;
return NULL;
}
return nalloc_realloc(ptr, size);
}
void* reallocarray(void* ptr, size_t nmemb, size_t size) {
if (nalloc_fail(size, "reallocarray")) {
errno = ENOMEM;
return NULL;
}
return nalloc_reallocarray(ptr, nmemb, size);
}
#ifdef __cplusplus
} // extern "C" {
#endif
#else // defined(WEBP_FUZZER_ENABLE_NALLOC)
#define nalloc_init(x)
#define nalloc_start(x, y)
#define nalloc_end()
#endif // defined(WEBP_FUZZER_ENABLE_NALLOC)
#endif // WEBP_TESTS_FUZZER_NALLOC_H_
+92
View File
@@ -0,0 +1,92 @@
#!/bin/bash
# Copyright 2018 Google Inc.
#
# 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.
#
################################################################################
# This script is meant to be run by the oss-fuzz infrastructure from the script
# https://github.com/google/oss-fuzz/blob/master/projects/libwebp/build.sh
# It builds the different fuzz targets.
# Only the libfuzzer engine is supported.
# To test changes to this file:
# - make changes and commit to your REPO
# - run:
# git clone --depth=1 git@github.com:google/oss-fuzz.git
# cd oss-fuzz
# - modify projects/libwebp/Dockerfile to point to your REPO
# - run:
# python3 infra/helper.py build_image libwebp
# # enter 'y' and wait for everything to be downloaded
# - run:
# python3 infra/helper.py build_fuzzers --sanitizer address libwebp
# # wait for the tests to be built
# And then run the fuzzer locally, for example:
# python3 infra/helper.py run_fuzzer libwebp \
# --sanitizer address \
# animencoder_fuzzer@AnimEncoder.AnimEncoderTest
set -eu
EXTRA_CMAKE_FLAGS=""
export CXXFLAGS="${CXXFLAGS} -DFUZZTEST_COMPATIBILITY_MODE -DWEBP_FUZZER_ENABLE_NALLOC"
EXTRA_CMAKE_FLAGS="-DFUZZTEST_COMPATIBILITY_MODE=libfuzzer"
# limit allocation size to reduce spurious OOMs
WEBP_CFLAGS="$CFLAGS -DWEBP_MAX_IMAGE_SIZE=838860800" # 800MiB
export CFLAGS="$WEBP_CFLAGS"
cmake -S . -B build -DWEBP_BUILD_FUZZTEST=ON ${EXTRA_CMAKE_FLAGS}
cd build && make -j$(nproc) && cd ..
find $SRC/libwebp-test-data -type f -size -32k -iname "*.webp" \
-exec zip -qju fuzz_seed_corpus.zip "{}" \;
# The following is taken from https://github.com/google/oss-fuzz/blob/31ac7244748ea7390015455fb034b1f4eda039d9/infra/base-images/base-builder/compile_fuzztests.sh#L59
# Iterate the fuzz binaries and list each fuzz entrypoint in the binary. For
# each entrypoint create a wrapper script that calls into the binaries the
# given entrypoint as argument.
# The scripts will be named:
# {binary_name}@{fuzztest_entrypoint}
FUZZ_TEST_BINARIES_OUT_PATHS=$(find ./build/tests/fuzzer/ -executable -type f)
echo "Fuzz binaries: $FUZZ_TEST_BINARIES_OUT_PATHS"
for fuzz_main_file in $FUZZ_TEST_BINARIES_OUT_PATHS; do
FUZZ_TESTS=$($fuzz_main_file --list_fuzz_tests | cut -d ' ' -f 4)
cp -f ${fuzz_main_file} $OUT/
fuzz_basename=$(basename $fuzz_main_file)
chmod -x $OUT/$fuzz_basename
for fuzz_entrypoint in $FUZZ_TESTS; do
TARGET_FUZZER="${fuzz_basename}@$fuzz_entrypoint"
# Write executer script
cat << EOF > $OUT/$TARGET_FUZZER
#!/bin/bash
# LLVMFuzzerTestOneInput for fuzzer detection.
this_dir=\$(dirname "\$0")
export TEST_DATA_DIRS=\$this_dir/corpus
export ASAN_OPTIONS="\${ASAN_OPTIONS}:allocator_may_return_null=1"
chmod +x \$this_dir/$fuzz_basename
\$this_dir/$fuzz_basename --fuzz=$fuzz_entrypoint -- \$@
chmod -x \$this_dir/$fuzz_basename
EOF
chmod +x $OUT/$TARGET_FUZZER
if grep -q "nalloc_init" $fuzz_main_file; then
cp $OUT/$TARGET_FUZZER $OUT/${TARGET_FUZZER}_nalloc
sed -i -e 's/^\$this_dir/NALLOC_FREQ=32 \$this_dir/' \
$OUT/${TARGET_FUZZER}_nalloc
fi
done
# Copy data.
cp fuzz_seed_corpus.zip $OUT/${fuzz_basename}_seed_corpus.zip
cp tests/fuzzer/fuzz.dict $OUT/${fuzz_basename}.dict
done
+10
View File
@@ -0,0 +1,10 @@
#!/bin/sh
# Fixes for https://github.com/google/fuzztest/issues/1124
sed -i -e "s/-fsanitize=address//g" -e "s/-DADDRESS_SANITIZER//g" \
./cmake/FuzzTestFlagSetup.cmake
# Fixes for https://github.com/google/fuzztest/issues/1125
before="if (IsEnginePlaceholderInput(data)) return;"
after="if (data.size() == 0) return;"
sed -i "s/${before}/${after}/" ./fuzztest/internal/compatibility_mode.cc
sed -i "s/set(GTEST_HAS_ABSL ON)/set(GTEST_HAS_ABSL OFF)/" \
./cmake/BuildDependencies.cmake
+103
View File
@@ -0,0 +1,103 @@
// Copyright 2018 Google Inc.
//
// 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 <cstddef>
#include <cstdint>
#include <cstdlib>
#include <string_view>
#include "./fuzz_utils.h"
#include "webp/decode.h"
#include "webp/types.h"
namespace {
void SimpleApiTest(std::string_view data_in) {
const uint8_t* const data = reinterpret_cast<const uint8_t*>(data_in.data());
const size_t size = data_in.size();
int w, h;
if (!WebPGetInfo(data, size, &w, &h)) return;
if ((size_t)w * h > fuzz_utils::kFuzzPxLimit) return;
const uint8_t value = fuzz_utils::FuzzHash(data, size);
uint8_t* buf = NULL;
// For *Into functions, which decode into an external buffer, an
// intentionally too small buffer can be given with low probability.
if (value < 0x16) {
buf = WebPDecodeRGBA(data, size, &w, &h);
} else if (value < 0x2b) {
buf = WebPDecodeBGRA(data, size, &w, &h);
#if !defined(WEBP_REDUCE_CSP)
} else if (value < 0x40) {
buf = WebPDecodeARGB(data, size, &w, &h);
} else if (value < 0x55) {
buf = WebPDecodeRGB(data, size, &w, &h);
} else if (value < 0x6a) {
buf = WebPDecodeBGR(data, size, &w, &h);
#endif // !defined(WEBP_REDUCE_CSP)
} else if (value < 0x7f) {
uint8_t *u, *v;
int stride, uv_stride;
buf = WebPDecodeYUV(data, size, &w, &h, &u, &v, &stride, &uv_stride);
} else if (value < 0xe8) {
const int stride = (value < 0xbe ? 4 : 3) * w;
size_t buf_size = stride * h;
if (value % 0x10 == 0) buf_size--;
uint8_t* const ext_buf = (uint8_t*)malloc(buf_size);
if (value < 0x94) {
(void)WebPDecodeRGBAInto(data, size, ext_buf, buf_size, stride);
#if !defined(WEBP_REDUCE_CSP)
} else if (value < 0xa9) {
(void)WebPDecodeARGBInto(data, size, ext_buf, buf_size, stride);
} else if (value < 0xbe) {
(void)WebPDecodeBGRInto(data, size, ext_buf, buf_size, stride);
} else if (value < 0xd3) {
(void)WebPDecodeRGBInto(data, size, ext_buf, buf_size, stride);
#endif // !defined(WEBP_REDUCE_CSP)
} else {
(void)WebPDecodeBGRAInto(data, size, ext_buf, buf_size, stride);
}
free(ext_buf);
} else {
size_t luma_size = w * h;
const int uv_stride = (w + 1) / 2;
size_t u_size = uv_stride * (h + 1) / 2;
size_t v_size = uv_stride * (h + 1) / 2;
if (value % 0x10 == 0) {
if (size & 1) luma_size--;
if (size & 2) u_size--;
if (size & 4) v_size--;
}
uint8_t* const luma_buf = (uint8_t*)malloc(luma_size);
uint8_t* const u_buf = (uint8_t*)malloc(u_size);
uint8_t* const v_buf = (uint8_t*)malloc(v_size);
(void)WebPDecodeYUVInto(data, size, luma_buf, luma_size,
w /* luma_stride */, u_buf, u_size, uv_stride,
v_buf, v_size, uv_stride);
free(luma_buf);
free(u_buf);
free(v_buf);
}
if (buf) WebPFree(buf);
}
} // namespace
FUZZ_TEST(SimpleApi, SimpleApiTest)
.WithDomains(fuzztest::String().WithMaxSize(fuzz_utils::kMaxWebPFileSize +
1));
+46
View File
@@ -0,0 +1,46 @@
// Copyright 2024 Google Inc.
//
// 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 <cstdint>
#include <string_view>
#include "./nalloc.h"
#include "tests/fuzzer/fuzz_utils.h"
#include "webp/mux_types.h"
// Don't do that at home!
#define main exec_main
#include "examples/webpinfo.c"
#undef main
void WebPInfoTest(std::string_view data) {
nalloc_init(nullptr);
nalloc_start(reinterpret_cast<const uint8_t*>(data.data()), data.size());
WebPInfo webp_info;
WebPInfoInit(&webp_info);
webp_info.quiet = 1;
webp_info.show_summary = 0;
webp_info.show_diagnosis = 0;
webp_info.parse_bitstream = 1;
WebPData webp_data = {reinterpret_cast<const uint8_t*>(data.data()),
data.size()};
AnalyzeWebP(&webp_info, &webp_data);
nalloc_end();
}
FUZZ_TEST(WebPInfo, WebPInfoTest)
.WithDomains(fuzztest::String().WithMaxSize(fuzz_utils::kMaxWebPFileSize +
1));