aboutsummaryrefslogtreecommitdiff
path: root/tests/fuzzer/animation_api_fuzzer.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/fuzzer/animation_api_fuzzer.c')
-rw-r--r--tests/fuzzer/animation_api_fuzzer.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/tests/fuzzer/animation_api_fuzzer.c b/tests/fuzzer/animation_api_fuzzer.c
new file mode 100644
index 00000000..30d60744
--- /dev/null
+++ b/tests/fuzzer/animation_api_fuzzer.c
@@ -0,0 +1,78 @@
+// 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 "./fuzz_utils.h"
+#include "webp/decode.h"
+#include "webp/demux.h"
+#include "webp/mux_types.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) {
+ WebPData webp_data;
+ WebPDataInit(&webp_data);
+ webp_data.size = size;
+ webp_data.bytes = data;
+
+ // WebPAnimDecoderNew uses WebPDemux internally to calloc canvas size.
+ WebPDemuxer* const demux = WebPDemux(&webp_data);
+ if (!demux) return 0;
+ 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 > kFuzzPxLimit) {
+ WebPDemuxDelete(demux);
+ return 0;
+ }
+
+ // In addition to canvas size, check each frame separately.
+ WebPIterator iter;
+ for (int i = 0; i < 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 > kFuzzPxLimit) { // image size of the frame payload
+ WebPDemuxReleaseIterator(&iter);
+ WebPDemuxDelete(demux);
+ return 0;
+ }
+ }
+ }
+
+ WebPDemuxReleaseIterator(&iter);
+ WebPDemuxDelete(demux);
+
+ WebPAnimDecoderOptions dec_options;
+ if (!WebPAnimDecoderOptionsInit(&dec_options)) return 0;
+
+ dec_options.use_threads = size & 1;
+ // Animations only support 4 (of 12) modes.
+ dec_options.color_mode = (WEBP_CSP_MODE)(size % MODE_LAST);
+ if (dec_options.color_mode != MODE_BGRA &&
+ dec_options.color_mode != MODE_rgbA &&
+ dec_options.color_mode != MODE_bgrA) {
+ dec_options.color_mode = MODE_RGBA;
+ }
+
+ WebPAnimDecoder* dec = WebPAnimDecoderNew(&webp_data, &dec_options);
+ if (!dec) return 0;
+
+ for (int i = 0; i < kFuzzFrameLimit; i++) {
+ uint8_t* buf;
+ int timestamp;
+ if (!WebPAnimDecoderGetNext(dec, &buf, &timestamp)) break;
+ }
+
+ WebPAnimDecoderDelete(dec);
+ return 0;
+}