1 // Copyright 2018 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ////////////////////////////////////////////////////////////////////////////////
16
17 #include "./fuzz_utils.h"
18 #include "src/webp/decode.h"
19 #include "src/webp/demux.h"
20 #include "src/webp/mux_types.h"
21
LLVMFuzzerTestOneInput(const uint8_t * const data,size_t size)22 int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) {
23 WebPData webp_data;
24 WebPDataInit(&webp_data);
25 webp_data.size = size;
26 webp_data.bytes = data;
27
28 // WebPAnimDecoderNew uses WebPDemux internally to calloc canvas size.
29 WebPDemuxer* const demux = WebPDemux(&webp_data);
30 if (!demux) return 0;
31 const uint32_t cw = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH);
32 const uint32_t ch = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT);
33 if ((size_t)cw * ch > kFuzzPxLimit) {
34 WebPDemuxDelete(demux);
35 return 0;
36 }
37
38 // In addition to canvas size, check each frame separately.
39 WebPIterator iter;
40 for (int i = 0; i < kFuzzFrameLimit; i++) {
41 if (!WebPDemuxGetFrame(demux, i + 1, &iter)) break;
42 int w, h;
43 if (WebPGetInfo(iter.fragment.bytes, iter.fragment.size, &w, &h)) {
44 if ((size_t)w * h > kFuzzPxLimit) { // image size of the frame payload
45 WebPDemuxReleaseIterator(&iter);
46 WebPDemuxDelete(demux);
47 return 0;
48 }
49 }
50 }
51
52 WebPDemuxReleaseIterator(&iter);
53 WebPDemuxDelete(demux);
54
55 WebPAnimDecoderOptions dec_options;
56 if (!WebPAnimDecoderOptionsInit(&dec_options)) return 0;
57
58 dec_options.use_threads = size & 1;
59 // Animations only support 4 (of 12) modes.
60 dec_options.color_mode = (WEBP_CSP_MODE)(size % MODE_LAST);
61 if (dec_options.color_mode != MODE_BGRA &&
62 dec_options.color_mode != MODE_rgbA &&
63 dec_options.color_mode != MODE_bgrA) {
64 dec_options.color_mode = MODE_RGBA;
65 }
66
67 WebPAnimDecoder* dec = WebPAnimDecoderNew(&webp_data, &dec_options);
68 if (!dec) return 0;
69
70 for (int i = 0; i < kFuzzFrameLimit; i++) {
71 uint8_t* buf;
72 int timestamp;
73 if (!WebPAnimDecoderGetNext(dec, &buf, ×tamp)) break;
74 }
75
76 WebPAnimDecoderDelete(dec);
77 return 0;
78 }
79