• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <cstddef>
18 #include <cstdint>
19 #include <string_view>
20 
21 #include "./fuzz_utils.h"
22 #include "src/webp/decode.h"
23 #include "src/webp/demux.h"
24 #include "src/webp/mux_types.h"
25 
26 namespace {
27 
AnimationApiTest(std::string_view blob,bool use_threads,WEBP_CSP_MODE color_mode)28 void AnimationApiTest(std::string_view blob, bool use_threads,
29                       WEBP_CSP_MODE color_mode) {
30   const size_t size = blob.size();
31   WebPData webp_data;
32   WebPDataInit(&webp_data);
33   webp_data.size = size;
34   webp_data.bytes = reinterpret_cast<const uint8_t*>(blob.data());
35 
36   // WebPAnimDecoderNew uses WebPDemux internally to calloc canvas size.
37   WebPDemuxer* const demux = WebPDemux(&webp_data);
38   if (!demux) return;
39   const uint32_t cw = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH);
40   const uint32_t ch = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT);
41   if ((size_t)cw * ch > fuzz_utils::kFuzzPxLimit) {
42     WebPDemuxDelete(demux);
43     return;
44   }
45 
46   // In addition to canvas size, check each frame separately.
47   WebPIterator iter;
48   for (int i = 0; i < fuzz_utils::kFuzzFrameLimit; i++) {
49     if (!WebPDemuxGetFrame(demux, i + 1, &iter)) break;
50     int w, h;
51     if (WebPGetInfo(iter.fragment.bytes, iter.fragment.size, &w, &h)) {
52       if ((size_t)w * h >
53           fuzz_utils::kFuzzPxLimit) {  // image size of the frame payload
54         WebPDemuxReleaseIterator(&iter);
55         WebPDemuxDelete(demux);
56         return;
57       }
58     }
59   }
60 
61   WebPDemuxReleaseIterator(&iter);
62   WebPDemuxDelete(demux);
63 
64   WebPAnimDecoderOptions dec_options;
65   if (!WebPAnimDecoderOptionsInit(&dec_options)) return;
66 
67   dec_options.use_threads = use_threads;
68   dec_options.color_mode = color_mode;
69 
70   WebPAnimDecoder* dec = WebPAnimDecoderNew(&webp_data, &dec_options);
71   if (!dec) return;
72 
73   for (int i = 0; i < fuzz_utils::kFuzzFrameLimit; i++) {
74     uint8_t* buf;
75     int timestamp;
76     if (!WebPAnimDecoderGetNext(dec, &buf, &timestamp)) break;
77   }
78 
79   WebPAnimDecoderDelete(dec);
80 }
81 
82 }  // namespace
83 
84 FUZZ_TEST(AnimationApi, AnimationApiTest)
85     .WithDomains(
86         fuzztest::String()
87             .WithMaxSize(fuzz_utils::kMaxWebPFileSize + 1),
88         /*use_threads=*/fuzztest::Arbitrary<bool>(),
89         // Animations only support 4 (out of 12) modes.
90         fuzztest::ElementOf<WEBP_CSP_MODE>({MODE_RGBA, MODE_BGRA, MODE_rgbA,
91                                             MODE_bgrA}));
92