• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018-2024 Google LLC
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 #ifndef WEBP_TESTS_FUZZER_FUZZ_UTILS_H_
18 #define WEBP_TESTS_FUZZER_FUZZ_UTILS_H_
19 
20 #include <cstddef>
21 #include <cstdint>
22 #include <cstdlib>
23 #include <optional>
24 #include <string>
25 #include <string_view>
26 #include <utility>
27 #include <vector>
28 
29 #include "./img_alpha.h"
30 #include "./img_grid.h"
31 #include "./img_peak.h"
32 #include "src/dsp/cpu.h"
33 #include "src/webp/encode.h"
34 #include "fuzztest/fuzztest.h"
35 
36 namespace fuzz_utils {
37 
38 //------------------------------------------------------------------------------
39 // Arbitrary limits to prevent OOM, timeout, or slow execution.
40 
41 // The decoded image size, and for animations additionally the canvas size.
42 // Enabling some sanitizers slow down runtime significantly.
43 // Use a very low threshold in this case to avoid timeouts.
44 #if defined(__SANITIZE_ADDRESS__)  // GCC
45 static const size_t kFuzzPxLimit = 1024 * 1024 / 10;
46 #elif !defined(__has_feature)  // Clang
47 static const size_t kFuzzPxLimit = 1024 * 1024;
48 #elif __has_feature(address_sanitizer) || __has_feature(memory_sanitizer)
49 static const size_t kFuzzPxLimit = 1024 * 1024 / 18;
50 #else
51 static const size_t kFuzzPxLimit = 1024 * 1024;
52 #endif
53 
54 // Demuxed or decoded animation frames.
55 static const int kFuzzFrameLimit = 3;
56 
57 // Reads and sums (up to) 128 spread-out bytes.
FuzzHash(const uint8_t * const data,size_t size)58 static WEBP_INLINE uint8_t FuzzHash(const uint8_t* const data, size_t size) {
59   uint8_t value = 0;
60   size_t incr = size / 128;
61   if (!incr) incr = 1;
62   for (size_t i = 0; i < size; i += incr) value += data[i];
63   return value;
64 }
65 
66 #ifdef __cplusplus
67 extern "C" VP8CPUInfo VP8GetCPUInfo;
68 #else
69 extern VP8CPUInfo VP8GetCPUInfo;
70 #endif
71 
72 //------------------------------------------------------------------------------
73 
74 constexpr const uint8_t* kImagesData[] = {kImgAlphaData, kImgGridData,
75                                           kImgPeakData};
76 constexpr size_t kNumSourceImages =
77     sizeof(kImagesData) / sizeof(kImagesData[0]);
78 
79 WebPPicture GetSourcePicture(int image_index, bool use_argb);
80 
ArbitraryWebPConfig()81 static inline auto ArbitraryWebPConfig() {
82   return fuzztest::Map(
83       [](int lossless, int quality, int method, int image_hint, int segments,
84          int sns_strength, int filter_strength, int filter_sharpness,
85          int filter_type, int autofilter, int alpha_compression,
86          int alpha_filtering, int alpha_quality, int pass, int preprocessing,
87          int partitions, int partition_limit, int emulate_jpeg_size,
88          int thread_level, int low_memory, int near_lossless, int exact,
89          int use_delta_palette, int use_sharp_yuv) -> WebPConfig {
90         WebPConfig config;
91         if (!WebPConfigInit(&config)) abort();
92         config.lossless = lossless;
93         config.quality = quality;
94         config.method = method;
95         config.image_hint = (WebPImageHint)image_hint;
96         config.segments = segments;
97         config.sns_strength = sns_strength;
98         config.filter_strength = filter_strength;
99         config.filter_sharpness = filter_sharpness;
100         config.filter_type = filter_type;
101         config.autofilter = autofilter;
102         config.alpha_compression = alpha_compression;
103         config.alpha_filtering = alpha_filtering;
104         config.alpha_quality = alpha_quality;
105         config.pass = pass;
106         config.show_compressed = 1;
107         config.preprocessing = preprocessing;
108         config.partitions = partitions;
109         config.partition_limit = 10 * partition_limit;
110         config.emulate_jpeg_size = emulate_jpeg_size;
111         config.thread_level = thread_level;
112         config.low_memory = low_memory;
113         config.near_lossless = 20 * near_lossless;
114         config.exact = exact;
115         config.use_delta_palette = use_delta_palette;
116         config.use_sharp_yuv = use_sharp_yuv;
117         if (!WebPValidateConfig(&config)) abort();
118         return config;
119       },
120       /*lossless=*/fuzztest::InRange<int>(0, 1),
121       /*quality=*/fuzztest::InRange<int>(0, 100),
122       /*method=*/fuzztest::InRange<int>(0, 6),
123       /*image_hint=*/fuzztest::InRange<int>(0, WEBP_HINT_LAST - 1),
124       /*segments=*/fuzztest::InRange<int>(1, 4),
125       /*sns_strength=*/fuzztest::InRange<int>(0, 100),
126       /*filter_strength=*/fuzztest::InRange<int>(0, 100),
127       /*filter_sharpness=*/fuzztest::InRange<int>(0, 7),
128       /*filter_type=*/fuzztest::InRange<int>(0, 1),
129       /*autofilter=*/fuzztest::InRange<int>(0, 1),
130       /*alpha_compression=*/fuzztest::InRange<int>(0, 1),
131       /*alpha_filtering=*/fuzztest::InRange<int>(0, 2),
132       /*alpha_quality=*/fuzztest::InRange<int>(0, 100),
133       /*pass=*/fuzztest::InRange<int>(1, 10),
134       /*preprocessing=*/fuzztest::InRange<int>(0, 2),
135       /*partitions=*/fuzztest::InRange<int>(0, 3),
136       /*partition_limit=*/fuzztest::InRange<int>(0, 10),
137       /*emulate_jpeg_size=*/fuzztest::InRange<int>(0, 1),
138       /*thread_level=*/fuzztest::InRange<int>(0, 1),
139       /*low_memory=*/fuzztest::InRange<int>(0, 1),
140       /*near_lossless=*/fuzztest::InRange<int>(0, 5),
141       /*exact=*/fuzztest::InRange<int>(0, 1),
142       /*use_delta_palette=*/fuzztest::InRange<int>(0, 1),
143       /*use_sharp_yuv=*/fuzztest::InRange<int>(0, 1));
144 }
145 
146 struct CropOrScaleParams {
147   bool alter_input;
148   bool crop_or_scale;
149   int width_ratio;
150   int height_ratio;
151   int left_ratio;
152   int top_ratio;
153 };
154 
ArbitraryCropOrScaleParams()155 static inline auto ArbitraryCropOrScaleParams() {
156   return fuzztest::Map(
157       [](const std::optional<std::pair<int, int>>& width_height_ratio,
158          const std::optional<std::pair<int, int>>& left_top_ratio)
159           -> CropOrScaleParams {
160         CropOrScaleParams params;
161         params.alter_input = width_height_ratio.has_value();
162         if (params.alter_input) {
163           params.width_ratio = width_height_ratio->first;
164           params.height_ratio = width_height_ratio->second;
165           params.crop_or_scale = left_top_ratio.has_value();
166           if (params.crop_or_scale) {
167             params.left_ratio = left_top_ratio->first;
168             params.top_ratio = left_top_ratio->second;
169           }
170         }
171         return params;
172       },
173       fuzztest::OptionalOf(
174           fuzztest::PairOf(fuzztest::InRange(1, 8), fuzztest::InRange(1, 8))),
175       fuzztest::OptionalOf(
176           fuzztest::PairOf(fuzztest::InRange(1, 8), fuzztest::InRange(1, 8))));
177 }
178 
179 // Crops or scales a picture according to the given params.
180 int CropOrScale(WebPPicture* pic, const CropOrScaleParams& params);
181 
182 // Imposes a level of optimization among one of the kMaxOptimizationIndex+1
183 // possible values: OnlyC, ForceSlowSSSE3, NoSSE41, NoAVX, default.
184 static constexpr uint32_t kMaxOptimizationIndex = 4;
185 void SetOptimization(VP8CPUInfo default_VP8GetCPUInfo, uint32_t index);
186 
187 //------------------------------------------------------------------------------
188 
189 // See https://developers.google.com/speed/webp/docs/riff_container.
190 static constexpr size_t kMaxWebPFileSize = (1ull << 32) - 2;  // 4 GiB - 2
191 
192 std::vector<std::string> GetDictionaryFromFiles(
193     const std::vector<std::string_view>& file_paths);
194 
195 // Checks whether the binary blob containing a JPEG or WebP is too big for the
196 // fuzzer.
197 bool IsImageTooBig(const uint8_t* data, size_t size);
198 
199 }  // namespace fuzz_utils
200 
201 #endif  // WEBP_TESTS_FUZZER_FUZZ_UTILS_H_
202