/src/libwebp/tests/fuzzer/animdecoder_fuzzer.cc
Line | Count | Source |
1 | | // Copyright 2020 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> |
20 | | #include <string_view> |
21 | | |
22 | | #include "./fuzz_utils.h" |
23 | | #include "./nalloc.h" |
24 | | #include "gtest/gtest.h" |
25 | | #include "imageio/imageio_util.h" |
26 | | #include "webp/decode.h" |
27 | | #include "webp/demux.h" |
28 | | #include "webp/mux_types.h" |
29 | | |
30 | | namespace { |
31 | | |
32 | 8.27k | void AnimDecoderTest(std::string_view blob) { |
33 | 8.27k | const uint8_t* const data = reinterpret_cast<const uint8_t*>(blob.data()); |
34 | 8.27k | const size_t size = blob.size(); |
35 | 8.27k | nalloc_init(nullptr); |
36 | 8.27k | nalloc_start(data, size); |
37 | | |
38 | | // WebPAnimDecoderGetInfo() is too late to check the canvas size as |
39 | | // WebPAnimDecoderNew() will handle the allocations. |
40 | 8.27k | const size_t kMaxNumBytes = 2684354560; // RSS (resident set size) limit. |
41 | 8.27k | const size_t kMaxNumPixels = kMaxNumBytes / 4; // At most ARGB. |
42 | 8.27k | const size_t kMaxNumPixelsSafe = kMaxNumPixels / 2; // Allow one buffer copy. |
43 | 8.27k | WebPBitstreamFeatures features; |
44 | 8.27k | if (WebPGetFeatures(data, size, &features) == VP8_STATUS_OK) { |
45 | 7.59k | if (!ImgIoUtilCheckSizeArgumentsOverflow(features.width * 4, |
46 | 7.59k | features.height) || |
47 | 7.53k | static_cast<size_t>(features.width) * features.height > |
48 | 7.53k | kMaxNumPixelsSafe) { |
49 | 57 | nalloc_end(); |
50 | 57 | return; |
51 | 57 | } |
52 | 7.59k | } |
53 | | |
54 | | // decode everything as an animation |
55 | 8.22k | WebPData webp_data = {data, size}; |
56 | 8.22k | WebPAnimDecoder* const dec = WebPAnimDecoderNew(&webp_data, nullptr); |
57 | 8.22k | if (dec == nullptr) { |
58 | 2.95k | nalloc_end(); |
59 | 2.95k | return; |
60 | 2.95k | } |
61 | | |
62 | 5.26k | WebPAnimInfo info; |
63 | 5.26k | if (!WebPAnimDecoderGetInfo(dec, &info)) goto End; |
64 | 5.26k | if (!ImgIoUtilCheckSizeArgumentsOverflow(info.canvas_width * 4, |
65 | 5.26k | info.canvas_height)) { |
66 | 0 | goto End; |
67 | 0 | } |
68 | | |
69 | 6.04k | while (WebPAnimDecoderHasMoreFrames(dec)) { |
70 | 5.26k | uint8_t* buf; |
71 | 5.26k | int timestamp; |
72 | 5.26k | if (!WebPAnimDecoderGetNext(dec, &buf, ×tamp)) break; |
73 | 5.26k | } |
74 | 5.26k | End: |
75 | 5.26k | WebPAnimDecoderDelete(dec); |
76 | 5.26k | nalloc_end(); |
77 | 5.26k | } |
78 | | |
79 | | } // namespace |
80 | | |
81 | | FUZZ_TEST(AnimDecoder, AnimDecoderTest) |
82 | | .WithDomains(fuzztest::String().WithMaxSize(fuzz_utils::kMaxWebPFileSize + |
83 | | 1)); |
84 | | |
85 | 0 | TEST(AnimDecoder, Buganizer498967090) { |
86 | 0 | AnimDecoderTest(std::string( |
87 | 0 | "ALPH\000\000\000\000\000\000\000\000\003\000\000\000\014EBPVP8 " |
88 | 0 | "\030\000\000\0000\001\000\235\001*\002\000\001\000\003\0004%" |
89 | 0 | "\244\000\003~\000*\316\373\224\"AFM\"<0\334\"\231J\002`" |
90 | 0 | "\256\233\233\233\233\272\000\000", |
91 | 0 | 72)); |
92 | 0 | } |