webp_animencoder: Add target to fuzz animation encoding (#1935)

* Add new fuzz target for encoding and misc

- Add fuzz_webp_enc_dec and adapt Dockerfile, build.sh
- Lint existing targets
- Add license headers
- Increase fuzz.dict

* webp_enc_dec: Convert input images to inline C arrays

Local files are not available on oss-fuzz servers.

* webp_enc_dec: Fix timeout by skipping crusher

The target fuzz_webp_enc_dec with msan crashes (timeout)
on a 128*128px image encoding with max compression (crusher).
Reduce crusher encoding to 16*16px and below.
Bug report 10423

* webp_enc_dec: Replace cruncher by lossy alpha encoding

The target fuzz_webp_enc_dec with msan crashes (timeout)
during encoding with max compression (cruncher).
Reduce alpha cruncher encoding to 16*16px and below.
Bug report 10634

* webp_enc_dec: Clamp slow parameters for big images

The target fuzz_webp_enc_dec with ubsan crashes (timeout)
during encoding with heavy compression. The cause can not
be easily removed without reducing performance.
Clamp compression parameters for images bigger than 16*16.
Bug report 10700

* webp_enc_dec: Limit alpha_quality to 99 when method is 6

The target fuzz_webp_enc_dec with asan crashes (timeout)
during encoding with heavy alpha compression.
Clamp alpha compression parameters for images bigger than 16*16.
Bug report 10838

* webp_animencoder: Add target to fuzz animation encoding

Add fuzz_webp_animencoder.cc and modify Dockerfile, build.sh
accordingly.
The thresholds for input size and encoding parameters are low
to prevent timeouts.
Some functions used by fuzz_webp_animencoder and fuzz_webp_enc_dec
have been moved to fuzz.h.
This commit is contained in:
YannisGuyon 2018-11-07 20:17:08 +01:00 committed by mbarbella-chromium
parent 08bb5d9bd7
commit 1ad8633819
5 changed files with 358 additions and 153 deletions

View File

@ -27,6 +27,7 @@ COPY img_alpha.h img_grid.h img_peak.h $SRC/
COPY fuzz_simple_api.c $SRC/
COPY fuzz_advanced_api.c $SRC/
COPY fuzz_animation_api.c $SRC/
COPY fuzz_webp_animencoder.cc $SRC/
COPY fuzz_demux_api.c $SRC/
COPY fuzz_webp_enc_dec.cc $SRC/
WORKDIR libwebp

View File

@ -35,7 +35,7 @@ find $SRC/libwebp-test-data -type f -size -32k -iname "*.webp" \
-exec zip -qju fuzz_seed_corpus.zip "{}" \;
# Simple Decoding API
$CC $CFLAGS -Isrc -c $SRC/fuzz_simple_api.c
$CC $CFLAGS -Isrc -I. -c $SRC/fuzz_simple_api.c
$CXX $CXXFLAGS -lFuzzingEngine \
fuzz_simple_api.o -o $OUT/fuzz_simple_api \
src/.libs/libwebp.a
@ -43,7 +43,7 @@ cp fuzz_seed_corpus.zip $OUT/fuzz_simple_api_seed_corpus.zip
cp $SRC/fuzz.dict $OUT/fuzz_simple_api.dict
# Advanced Decoding API
$CC $CFLAGS -Isrc -c $SRC/fuzz_advanced_api.c
$CC $CFLAGS -Isrc -I. -c $SRC/fuzz_advanced_api.c
$CXX $CXXFLAGS -lFuzzingEngine \
fuzz_advanced_api.o -o $OUT/fuzz_advanced_api \
src/.libs/libwebp.a
@ -51,7 +51,7 @@ cp fuzz_seed_corpus.zip $OUT/fuzz_advanced_api_seed_corpus.zip
cp $SRC/fuzz.dict $OUT/fuzz_advanced_api.dict
# Animation Decoding API
$CC $CFLAGS -Isrc -c $SRC/fuzz_animation_api.c
$CC $CFLAGS -Isrc -I. -c $SRC/fuzz_animation_api.c
$CXX $CXXFLAGS -lFuzzingEngine \
fuzz_animation_api.o -o $OUT/fuzz_animation_api \
src/demux/.libs/libwebpdemux.a \
@ -59,8 +59,16 @@ $CXX $CXXFLAGS -lFuzzingEngine \
cp fuzz_seed_corpus.zip $OUT/fuzz_animation_api_seed_corpus.zip
cp $SRC/fuzz.dict $OUT/fuzz_animation_api.dict
# Animation Encoding API
$CC $CFLAGS -Isrc -I. -c $SRC/fuzz_webp_animencoder.cc
$CXX $CXXFLAGS -lFuzzingEngine \
fuzz_webp_animencoder.o -o $OUT/fuzz_webp_animencoder \
src/mux/.libs/libwebpmux.a \
src/.libs/libwebp.a
cp fuzz_seed_corpus.zip $OUT/fuzz_webp_animencoder_seed_corpus.zip
# (De)mux API
$CC $CFLAGS -Isrc -c $SRC/fuzz_demux_api.c
$CC $CFLAGS -Isrc -I. -c $SRC/fuzz_demux_api.c
$CXX $CXXFLAGS -lFuzzingEngine \
fuzz_demux_api.o -o $OUT/fuzz_demux_api \
src/demux/.libs/libwebpdemux.a src/mux/.libs/libwebpmux.a \

View File

@ -17,6 +17,13 @@
#include <stdint.h>
#include <stdlib.h>
#include "dsp/dsp.h"
#include "img_alpha.h"
#include "img_grid.h"
#include "img_peak.h"
#include "webp/encode.h"
//------------------------------------------------------------------------------
// Arbitrary limits to prevent OOM, timeout, or slow execution.
//
// The decoded image size, and for animations additionally the canvas size.
@ -32,3 +39,152 @@ uint8_t FuzzHash(const uint8_t* const data, size_t size) {
for (size_t i = 0; i < size; i += incr) value += data[i];
return value;
}
//------------------------------------------------------------------------------
// Extract an integer in [0, max_value].
static uint32_t Extract(uint32_t max_value, const uint8_t data[], size_t size,
uint32_t* const bit_pos) {
uint32_t v = 0;
int range = 1;
while (*bit_pos < 8 * size && range <= max_value) {
const uint8_t mask = 1u << (*bit_pos & 7);
v = (v << 1) | !!(data[*bit_pos >> 3] & mask);
range <<= 1;
++*bit_pos;
}
return v % (max_value + 1);
}
//------------------------------------------------------------------------------
// Some functions to override VP8GetCPUInfo and disable some optimizations.
static VP8CPUInfo GetCPUInfo;
static int GetCPUInfoNoSSE41(CPUFeature feature) {
if (feature == kSSE4_1 || feature == kAVX) return 0;
return GetCPUInfo(feature);
}
static int GetCPUInfoNoAVX(CPUFeature feature) {
if (feature == kAVX) return 0;
return GetCPUInfo(feature);
}
static int GetCPUInfoForceSlowSSSE3(CPUFeature feature) {
if (feature == kSlowSSSE3 && GetCPUInfo(kSSE3)) {
return 1; // we have SSE3 -> force SlowSSSE3
}
return GetCPUInfo(feature);
}
static int GetCPUInfoOnlyC(CPUFeature feature) { return 0; }
static void ExtractAndDisableOptimizations(VP8CPUInfo default_VP8GetCPUInfo,
const uint8_t data[], size_t size,
uint32_t* const bit_pos) {
GetCPUInfo = default_VP8GetCPUInfo;
const VP8CPUInfo kVP8CPUInfos[5] = {GetCPUInfoOnlyC, GetCPUInfoForceSlowSSSE3,
GetCPUInfoNoSSE41, GetCPUInfoNoAVX,
GetCPUInfo};
int VP8GetCPUInfo_index = Extract(4, data, size, bit_pos);
VP8GetCPUInfo = kVP8CPUInfos[VP8GetCPUInfo_index];
}
//------------------------------------------------------------------------------
static int ExtractWebPConfig(WebPConfig* const config, const uint8_t data[],
size_t size, uint32_t* const bit_pos) {
if (config == NULL || !WebPConfigInit(config)) return 0;
config->lossless = Extract(1, data, size, bit_pos);
config->quality = Extract(100, data, size, bit_pos);
config->method = Extract(6, data, size, bit_pos);
config->image_hint =
(WebPImageHint)Extract(WEBP_HINT_LAST - 1, data, size, bit_pos);
config->segments = 1 + Extract(3, data, size, bit_pos);
config->sns_strength = Extract(100, data, size, bit_pos);
config->filter_strength = Extract(100, data, size, bit_pos);
config->filter_sharpness = Extract(7, data, size, bit_pos);
config->filter_type = Extract(1, data, size, bit_pos);
config->autofilter = Extract(1, data, size, bit_pos);
config->alpha_compression = Extract(1, data, size, bit_pos);
config->alpha_filtering = Extract(2, data, size, bit_pos);
config->alpha_quality = Extract(100, data, size, bit_pos);
config->pass = 1 + Extract(9, data, size, bit_pos);
config->show_compressed = 1;
config->preprocessing = Extract(2, data, size, bit_pos);
config->partitions = Extract(3, data, size, bit_pos);
config->partition_limit = 10 * Extract(10, data, size, bit_pos);
config->emulate_jpeg_size = Extract(1, data, size, bit_pos);
config->thread_level = Extract(1, data, size, bit_pos);
config->low_memory = Extract(1, data, size, bit_pos);
config->near_lossless = 20 * Extract(5, data, size, bit_pos);
config->exact = Extract(1, data, size, bit_pos);
config->use_delta_palette = Extract(1, data, size, bit_pos);
config->use_sharp_yuv = Extract(1, data, size, bit_pos);
return WebPValidateConfig(config);
}
//------------------------------------------------------------------------------
static int ExtractSourcePicture(WebPPicture* const pic,
const uint8_t data[], size_t size,
uint32_t* const bit_pos) {
if (pic == NULL) return 0;
// Pick a source picture.
const uint8_t* kImagesData[] = {
kImgAlphaData,
kImgGridData,
kImgPeakData
};
const int kImagesWidth[] = {
kImgAlphaWidth,
kImgGridWidth,
kImgPeakWidth
};
const int kImagesHeight[] = {
kImgAlphaHeight,
kImgGridHeight,
kImgPeakHeight
};
const size_t kNbImages = sizeof(kImagesData) / sizeof(kImagesData[0]);
const size_t image_index = Extract(kNbImages - 1, data, size, bit_pos);
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.
return WebPPictureImportRGBA(pic, image_data, pic->argb_stride);
}
//------------------------------------------------------------------------------
static int max(int a, int b) { return ((a < b) ? b : a); }
static int ExtractAndCropOrScale(WebPPicture* const pic, const uint8_t data[],
size_t size, uint32_t* const bit_pos) {
if (pic == NULL) return 0;
const int alter_input = Extract(1, data, size, bit_pos);
const int crop_or_scale = Extract(1, data, size, bit_pos);
const int width_ratio = 1 + Extract(7, data, size, bit_pos);
const int height_ratio = 1 + Extract(7, data, size, bit_pos);
if (alter_input) {
if (crop_or_scale) {
const uint32_t left_ratio = 1 + Extract(7, data, size, bit_pos);
const uint32_t top_ratio = 1 + Extract(7, data, size, bit_pos);
const int cropped_width = max(1, pic->width / width_ratio);
const int cropped_height = max(1, pic->height / height_ratio);
const int cropped_left = (pic->width - cropped_width) / left_ratio;
const int cropped_top = (pic->height - cropped_height) / top_ratio;
return WebPPictureCrop(pic, cropped_left, cropped_top, cropped_width,
cropped_height);
} else {
const int scaled_width = 1 + (pic->width * width_ratio) / 8;
const int scaled_height = 1 + (pic->height * height_ratio) / 8;
return WebPPictureRescale(pic, scaled_width, scaled_height);
}
}
return 1;
}

View File

@ -0,0 +1,165 @@
// 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 <stdio.h>
#include <stdlib.h>
#include "fuzz.h"
#include "webp/encode.h"
#include "webp/mux.h"
namespace {
const VP8CPUInfo default_VP8GetCPUInfo = VP8GetCPUInfo;
int AddFrame(WebPAnimEncoder** const enc,
const WebPAnimEncoderOptions& anim_config, int* const width,
int* const height, int timestamp_ms, const uint8_t data[],
size_t size, uint32_t* const bit_pos) {
if (enc == nullptr || width == nullptr || height == nullptr) {
fprintf(stderr, "NULL parameters.\n");
if (enc != nullptr) WebPAnimEncoderDelete(*enc);
abort();
}
// Init the source picture.
WebPPicture pic;
if (!WebPPictureInit(&pic)) {
fprintf(stderr, "WebPPictureInit failed.\n");
WebPAnimEncoderDelete(*enc);
abort();
}
pic.use_argb = Extract(1, data, size, bit_pos);
// Read the source picture.
if (!ExtractSourcePicture(&pic, data, size, bit_pos)) {
fprintf(stderr, "Can't read input image.\n");
WebPPictureFree(&pic);
abort();
}
// Crop and scale.
if (*enc == nullptr) { // First frame will set canvas width and height.
if (!ExtractAndCropOrScale(&pic, data, size, bit_pos)) {
fprintf(stderr, "ExtractAndCropOrScale failed.");
WebPPictureFree(&pic);
abort();
}
} else { // Other frames will be resized to the first frame's dimensions.
if (!WebPPictureRescale(&pic, *width, *height)) {
fprintf(stderr, "WebPPictureRescale failed. Size: %d,%d\n", *width,
*height);
WebPAnimEncoderDelete(*enc);
WebPPictureFree(&pic);
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) {
fprintf(stderr, "WebPAnimEncoderNew failed.\n");
WebPPictureFree(&pic);
abort();
}
}
// Create frame encoding config.
WebPConfig config;
if (!ExtractWebPConfig(&config, data, size, bit_pos)) {
fprintf(stderr, "ExtractWebPConfig failed.\n");
WebPAnimEncoderDelete(*enc);
WebPPictureFree(&pic);
abort();
}
// 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)) {
fprintf(stderr, "WebPEncode failed. Error code: %d\n", pic.error_code);
WebPAnimEncoderDelete(*enc);
WebPPictureFree(&pic);
abort();
}
WebPPictureFree(&pic);
return 1;
}
} // namespace
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) {
WebPAnimEncoder* enc = nullptr;
int width = 0, height = 0, timestamp_ms = 0;
uint32_t bit_pos = 0;
ExtractAndDisableOptimizations(default_VP8GetCPUInfo, data, size, &bit_pos);
// Extract a configuration from the packed bits.
WebPAnimEncoderOptions anim_config;
if (!WebPAnimEncoderOptionsInit(&anim_config)) {
fprintf(stderr, "WebPAnimEncoderOptionsInit failed.\n");
abort();
}
anim_config.minimize_size = Extract(1, data, size, &bit_pos);
anim_config.kmax = Extract(15, data, size, &bit_pos);
const int min_kmin = (anim_config.kmax > 1) ? (anim_config.kmax / 2) : 0;
const int max_kmin = (anim_config.kmax > 1) ? (anim_config.kmax - 1) : 0;
anim_config.kmin =
min_kmin + Extract((uint32_t)(max_kmin - min_kmin), data, size, &bit_pos);
anim_config.allow_mixed = Extract(1, data, size, &bit_pos);
anim_config.verbose = 0;
const int nb_frames = 1 + Extract(15, data, size, &bit_pos);
// For each frame.
for (int i = 0; i < nb_frames; ++i) {
if (!AddFrame(&enc, anim_config, &width, &height, timestamp_ms, data, size,
&bit_pos)) {
return 0;
}
timestamp_ms += (1 << (2 + Extract(15, data, size, &bit_pos))) +
Extract(1, data, size, &bit_pos); // [1..131073], arbitrary
}
// Assemble.
if (!WebPAnimEncoderAdd(enc, nullptr, timestamp_ms, nullptr)) {
fprintf(stderr, "Last WebPAnimEncoderAdd failed.");
WebPAnimEncoderDelete(enc);
abort();
}
WebPData webp_data;
WebPDataInit(&webp_data);
if (!WebPAnimEncoderAssemble(enc, &webp_data)) {
fprintf(stderr, "WebPAnimEncoderAssemble failed.");
WebPAnimEncoderDelete(enc);
WebPDataClear(&webp_data);
abort();
}
WebPAnimEncoderDelete(enc);
WebPDataClear(&webp_data);
return 0;
}

View File

@ -16,98 +16,20 @@
#include <stdio.h>
#include <stdlib.h>
#include "fuzz.h"
#include "webp/encode.h"
#include "webp/decode.h"
#include "img_alpha.h"
#include "img_grid.h"
#include "img_peak.h"
#include "dsp/dsp.h"
namespace {
const VP8CPUInfo LibGetCPUInfo = VP8GetCPUInfo;
const VP8CPUInfo default_VP8GetCPUInfo = VP8GetCPUInfo;
int GetCPUInfoNoSSE41(CPUFeature feature) {
if (feature == kSSE4_1 || feature == kAVX) return 0;
return LibGetCPUInfo(feature);
}
int GetCPUInfoNoAVX(CPUFeature feature) {
if (feature == kAVX) return 0;
return LibGetCPUInfo(feature);
}
int GetCPUInfoForceSlowSSSE3(CPUFeature feature) {
if (feature == kSlowSSSE3 && LibGetCPUInfo(kSSE3)) {
return 1; // we have SSE3 -> force SlowSSSE3
}
return LibGetCPUInfo(feature);
}
int GetCPUInfoOnlyC(CPUFeature feature) {
return false;
}
const VP8CPUInfo kVP8CPUInfos[5] = {
GetCPUInfoOnlyC, GetCPUInfoForceSlowSSSE3,
GetCPUInfoNoSSE41, GetCPUInfoNoAVX, LibGetCPUInfo
};
static uint32_t Extract(uint32_t max, const uint8_t data[], size_t size,
uint32_t* const bit_pos) {
uint32_t v = 0;
int range = 1;
while (*bit_pos < 8 * size && range <= max) {
const uint8_t mask = 1u << (*bit_pos & 7);
v = (v << 1) | !!(data[*bit_pos >> 3] & mask);
range <<= 1;
++*bit_pos;
}
return v % (max + 1);
}
static int max(int a, int b) { return ((a < b) ? b : a); }
} // namespace
} // namespace
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) {
// Extract a configuration from the packed bits.
WebPConfig config;
if (!WebPConfigInit(&config)) {
fprintf(stderr, "WebPConfigInit failed.\n");
abort();
}
uint32_t bit_pos = 0;
config.lossless = Extract(1, data, size, &bit_pos);
config.quality = Extract(100, data, size, &bit_pos);
config.method = Extract(6, data, size, &bit_pos);
config.image_hint =
(WebPImageHint)Extract(WEBP_HINT_LAST - 1, data, size, &bit_pos);
config.segments = 1 + Extract(3, data, size, &bit_pos);
config.sns_strength = Extract(100, data, size, &bit_pos);
config.filter_strength = Extract(100, data, size, &bit_pos);
config.filter_sharpness = Extract(7, data, size, &bit_pos);
config.filter_type = Extract(1, data, size, &bit_pos);
config.autofilter = Extract(1, data, size, &bit_pos);
config.alpha_compression = Extract(1, data, size, &bit_pos);
config.alpha_filtering = Extract(2, data, size, &bit_pos);
config.alpha_quality = Extract(100, data, size, &bit_pos);
config.pass = 1 + Extract(9, data, size, &bit_pos);
config.show_compressed = 1;
config.preprocessing = Extract(2, data, size, &bit_pos);
config.partitions = Extract(3, data, size, &bit_pos);
config.partition_limit = 10 * Extract(10, data, size, &bit_pos);
config.emulate_jpeg_size = Extract(1, data, size, &bit_pos);
config.thread_level = Extract(1, data, size, &bit_pos);
config.low_memory = Extract(1, data, size, &bit_pos);
config.near_lossless = 20 * Extract(5, data, size, &bit_pos);
config.exact = Extract(1, data, size, &bit_pos);
config.use_delta_palette = Extract(1, data, size, &bit_pos);
config.use_sharp_yuv = Extract(1, data, size, &bit_pos);
if (!WebPValidateConfig(&config)) {
fprintf(stderr, "WebPValidateConfig failed.\n");
abort();
}
ExtractAndDisableOptimizations(default_VP8GetCPUInfo, data, size, &bit_pos);
// Init the source picture.
WebPPicture pic;
@ -117,79 +39,35 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) {
}
pic.use_argb = Extract(1, data, size, &bit_pos);
VP8GetCPUInfo = kVP8CPUInfos[Extract(4, data, size, &bit_pos)];
// Pick a source picture.
const uint8_t* kImagesData[] = {
kImgAlphaData,
kImgGridData,
kImgPeakData
};
const int kImagesWidth[] = {
kImgAlphaWidth,
kImgGridWidth,
kImgPeakWidth
};
const int kImagesHeight[] = {
kImgAlphaHeight,
kImgGridHeight,
kImgPeakHeight
};
const size_t kNbImages = sizeof(kImagesData) / sizeof(kImagesData[0]);
const size_t image_index = Extract(kNbImages - 1, data, size, &bit_pos);
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)) {
fprintf(stderr, "Can't read input image: %zu\n", image_index);
// Read the source picture.
if (!ExtractSourcePicture(&pic, data, size, &bit_pos)) {
fprintf(stderr, "Can't read input image.\n");
WebPPictureFree(&pic);
abort();
}
// Crop and scale.
const bool alter_input = Extract(1, data, size, &bit_pos) != 0;
const bool crop_or_scale = Extract(1, data, size, &bit_pos) != 0;
const int width_ratio = 1 + Extract(7, data, size, &bit_pos);
const int height_ratio = 1 + Extract(7, data, size, &bit_pos);
if (alter_input) {
if (crop_or_scale) {
const uint32_t left_ratio = 1 + Extract(7, data, size, &bit_pos);
const uint32_t top_ratio = 1 + Extract(7, data, size, &bit_pos);
const int cropped_width = max(1, pic.width / width_ratio);
const int cropped_height = max(1, pic.height / height_ratio);
const int cropped_left = (pic.width - cropped_width) / left_ratio;
const int cropped_top = (pic.height - cropped_height) / top_ratio;
if (!WebPPictureCrop(&pic, cropped_left, cropped_top, cropped_width,
cropped_height)) {
fprintf(stderr, "WebPPictureCrop failed. Parameters: %d,%d,%d,%d\n",
cropped_left, cropped_top, cropped_width, cropped_height);
WebPPictureFree(&pic);
abort();
}
} else {
const int scaled_width = 1 + pic.width * width_ratio / 4;
const int scaled_height = 1 + pic.height * height_ratio / 4;
if (!WebPPictureRescale(&pic, scaled_width, scaled_height)) {
fprintf(stderr, "WebPPictureRescale failed. Parameters: %d,%d\n",
scaled_width, scaled_height);
WebPPictureFree(&pic);
abort();
}
}
if (!ExtractAndCropOrScale(&pic, data, size, &bit_pos)) {
fprintf(stderr, "ExtractAndCropOrScale failed.");
WebPPictureFree(&pic);
abort();
}
// Extract a configuration from the packed bits.
WebPConfig config;
if (!ExtractWebPConfig(&config, data, size, &bit_pos)) {
fprintf(stderr, "ExtractWebPConfig failed.\n");
abort();
}
// Skip slow settings on big images, it's likely to timeout.
if (pic.width * pic.height > 16 * 16) {
if (pic.width * pic.height > 32 * 32) {
if (config.lossless) {
if (config.quality >= 99.0f && config.method >= 5) {
if (config.quality > 99.0f && config.method >= 5) {
config.quality = 99.0f;
config.method = 5;
}
} else {
if (config.quality >= 99.0f && config.method == 6) {
if (config.quality > 99.0f && config.method == 6) {
config.quality = 99.0f;
}
}
@ -204,8 +82,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) {
pic.writer = WebPMemoryWrite;
pic.custom_ptr = &memory_writer;
if (!WebPEncode(&config, &pic)) {
fprintf(stderr, "WebPEncode failed. Error code: %d\nFile: %zu\n",
pic.error_code, image_index);
fprintf(stderr, "WebPEncode failed. Error code: %d\n", pic.error_code);
WebPMemoryWriterClear(&memory_writer);
WebPPictureFree(&pic);
abort();
@ -217,7 +94,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) {
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) {
fprintf(stderr, "WebPDecodeBGRA failed.\nFile: %zu\n", image_index);
fprintf(stderr, "WebPDecodeBGRA failed.\n");
WebPFree(rgba);
WebPMemoryWriterClear(&memory_writer);
WebPPictureFree(&pic);
@ -239,9 +116,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) {
}
}
if (v1 != v2) {
fprintf(stderr,
"Lossless compression failed pixel-exactness.\nFile: %zu\n",
image_index);
fprintf(stderr, "Lossless compression failed pixel-exactness.\n");
WebPFree(rgba);
WebPMemoryWriterClear(&memory_writer);
WebPPictureFree(&pic);