/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_view> |
20 | | |
21 | | #include "./fuzz_utils.h" |
22 | | #include "./nalloc.h" |
23 | | #include "imageio/imageio_util.h" |
24 | | #include "src/webp/decode.h" |
25 | | #include "src/webp/demux.h" |
26 | | #include "src/webp/mux_types.h" |
27 | | |
28 | | namespace { |
29 | | |
30 | 5.57k | void AnimDecoderTest(std::string_view blob) { |
31 | 5.57k | const uint8_t* const data = reinterpret_cast<const uint8_t*>(blob.data()); |
32 | 5.57k | const size_t size = blob.size(); |
33 | 5.57k | nalloc_init(nullptr); |
34 | 5.57k | nalloc_start(data, size); |
35 | | |
36 | | // WebPAnimDecoderGetInfo() is too late to check the canvas size as |
37 | | // WebPAnimDecoderNew() will handle the allocations. |
38 | 5.57k | const size_t kMaxNumBytes = 2684354560; // RSS (resident set size) limit. |
39 | 5.57k | const size_t kMaxNumPixels = kMaxNumBytes / 4; // At most ARGB. |
40 | 5.57k | const size_t kMaxNumPixelsSafe = kMaxNumPixels / 2; // Allow one buffer copy. |
41 | 5.57k | WebPBitstreamFeatures features; |
42 | 5.57k | if (WebPGetFeatures(data, size, &features) == VP8_STATUS_OK) { |
43 | 5.13k | if (!ImgIoUtilCheckSizeArgumentsOverflow(features.width * 4, |
44 | 5.13k | features.height) || |
45 | 5.11k | static_cast<size_t>(features.width) * features.height > |
46 | 5.11k | kMaxNumPixelsSafe) { |
47 | 18 | nalloc_end(); |
48 | 18 | return; |
49 | 18 | } |
50 | 5.13k | } |
51 | | |
52 | | // decode everything as an animation |
53 | 5.55k | WebPData webp_data = {data, size}; |
54 | 5.55k | WebPAnimDecoder* const dec = WebPAnimDecoderNew(&webp_data, nullptr); |
55 | 5.55k | if (dec == nullptr) { |
56 | 1.36k | nalloc_end(); |
57 | 1.36k | return; |
58 | 1.36k | } |
59 | | |
60 | 4.19k | WebPAnimInfo info; |
61 | 4.19k | if (!WebPAnimDecoderGetInfo(dec, &info)) goto End; |
62 | 4.19k | if (!ImgIoUtilCheckSizeArgumentsOverflow(info.canvas_width * 4, |
63 | 4.19k | info.canvas_height)) { |
64 | 0 | goto End; |
65 | 0 | } |
66 | | |
67 | 4.75k | while (WebPAnimDecoderHasMoreFrames(dec)) { |
68 | 4.19k | uint8_t* buf; |
69 | 4.19k | int timestamp; |
70 | 4.19k | if (!WebPAnimDecoderGetNext(dec, &buf, ×tamp)) break; |
71 | 4.19k | } |
72 | 4.19k | End: |
73 | 4.19k | WebPAnimDecoderDelete(dec); |
74 | 4.19k | nalloc_end(); |
75 | 4.19k | } |
76 | | |
77 | | } // namespace |
78 | | |
79 | | FUZZ_TEST(AnimDecoder, AnimDecoderTest) |
80 | | .WithDomains(fuzztest::String().WithMaxSize(fuzz_utils::kMaxWebPFileSize + |
81 | | 1)); |