aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYannisGuyon <7632072+YannisGuyon@users.noreply.github.com>2018-11-07 20:17:08 +0100
committermbarbella-chromium <41697236+mbarbella-chromium@users.noreply.github.com>2018-11-07 11:17:08 -0800
commit1ad8633819e2631ff6f1c11e28446343991f7fe0 (patch)
treecf2972c38c4edcdf80ca9d83eeddae23d2b2d3be
parent08bb5d9bd7d0820dc68ed59e6b8b201253b3728f (diff)
downloadoss-fuzz-1ad8633819e2631ff6f1c11e28446343991f7fe0.tar.gz
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.
-rw-r--r--projects/libwebp/Dockerfile1
-rw-r--r--projects/libwebp/build.sh16
-rw-r--r--projects/libwebp/fuzz.h156
-rw-r--r--projects/libwebp/fuzz_webp_animencoder.cc165
-rw-r--r--projects/libwebp/fuzz_webp_enc_dec.cc173
5 files changed, 358 insertions, 153 deletions
diff --git a/projects/libwebp/Dockerfile b/projects/libwebp/Dockerfile
index b00a937e0..081d36344 100644
--- a/projects/libwebp/Dockerfile
+++ b/projects/libwebp/Dockerfile
@@ -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
diff --git a/projects/libwebp/build.sh b/projects/libwebp/build.sh
index d432741ed..612f10ef8 100644
--- a/projects/libwebp/build.sh
+++ b/projects/libwebp/build.sh
@@ -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 \
diff --git a/projects/libwebp/fuzz.h b/projects/libwebp/fuzz.h
index d3e984b0d..408211f36 100644
--- a/projects/libwebp/fuzz.h
+++ b/projects/libwebp/fuzz.h
@@ -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;
+}
diff --git a/projects/libwebp/fuzz_webp_animencoder.cc b/projects/libwebp/fuzz_webp_animencoder.cc
new file mode 100644
index 000000000..f5cb2d13f
--- /dev/null
+++ b/projects/libwebp/fuzz_webp_animencoder.cc
@@ -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;
+}
diff --git a/projects/libwebp/fuzz_webp_enc_dec.cc b/projects/libwebp/fuzz_webp_enc_dec.cc
index c1830e5d1..5e3ef4276 100644
--- a/projects/libwebp/fuzz_webp_enc_dec.cc
+++ b/projects/libwebp/fuzz_webp_enc_dec.cc
@@ -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);