xref: /aosp_15_r20/external/webp/tests/fuzzer/animation_api_fuzzer.c (revision b2055c353e87c8814eb2b6b1b11112a1562253bd)
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, &timestamp)) break;
74   }
75 
76   WebPAnimDecoderDelete(dec);
77   return 0;
78 }
79