xref: /aosp_15_r20/external/webp/tests/fuzzer/fuzz_utils.h (revision b2055c353e87c8814eb2b6b1b11112a1562253bd)
1*b2055c35SXin Li // Copyright 2018 Google Inc.
2*b2055c35SXin Li //
3*b2055c35SXin Li // Licensed under the Apache License, Version 2.0 (the "License");
4*b2055c35SXin Li // you may not use this file except in compliance with the License.
5*b2055c35SXin Li // You may obtain a copy of the License at
6*b2055c35SXin Li //
7*b2055c35SXin Li //      http://www.apache.org/licenses/LICENSE-2.0
8*b2055c35SXin Li //
9*b2055c35SXin Li // Unless required by applicable law or agreed to in writing, software
10*b2055c35SXin Li // distributed under the License is distributed on an "AS IS" BASIS,
11*b2055c35SXin Li // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*b2055c35SXin Li // See the License for the specific language governing permissions and
13*b2055c35SXin Li // limitations under the License.
14*b2055c35SXin Li //
15*b2055c35SXin Li ////////////////////////////////////////////////////////////////////////////////
16*b2055c35SXin Li 
17*b2055c35SXin Li #ifndef WEBP_TESTS_FUZZER_FUZZ_UTILS_H_
18*b2055c35SXin Li #define WEBP_TESTS_FUZZER_FUZZ_UTILS_H_
19*b2055c35SXin Li 
20*b2055c35SXin Li #include <stdint.h>
21*b2055c35SXin Li #include <stdlib.h>
22*b2055c35SXin Li 
23*b2055c35SXin Li #include "./img_alpha.h"
24*b2055c35SXin Li #include "./img_grid.h"
25*b2055c35SXin Li #include "./img_peak.h"
26*b2055c35SXin Li #include "src/dsp/dsp.h"
27*b2055c35SXin Li #include "src/webp/encode.h"
28*b2055c35SXin Li 
29*b2055c35SXin Li //------------------------------------------------------------------------------
30*b2055c35SXin Li // Arbitrary limits to prevent OOM, timeout, or slow execution.
31*b2055c35SXin Li 
32*b2055c35SXin Li // The decoded image size, and for animations additionally the canvas size.
33*b2055c35SXin Li // Enabling some sanitizers slow down runtime significantly.
34*b2055c35SXin Li // Use a very low threshold in this case to avoid timeouts.
35*b2055c35SXin Li #if defined(__SANITIZE_ADDRESS__)  // GCC
36*b2055c35SXin Li static const size_t kFuzzPxLimit = 1024 * 1024 / 10;
37*b2055c35SXin Li #elif !defined(__has_feature)  // Clang
38*b2055c35SXin Li static const size_t kFuzzPxLimit = 1024 * 1024;
39*b2055c35SXin Li #elif __has_feature(address_sanitizer) || __has_feature(memory_sanitizer)
40*b2055c35SXin Li static const size_t kFuzzPxLimit = 1024 * 1024 / 18;
41*b2055c35SXin Li #else
42*b2055c35SXin Li static const size_t kFuzzPxLimit = 1024 * 1024;
43*b2055c35SXin Li #endif
44*b2055c35SXin Li 
45*b2055c35SXin Li // Demuxed or decoded animation frames.
46*b2055c35SXin Li static const int kFuzzFrameLimit = 3;
47*b2055c35SXin Li 
48*b2055c35SXin Li // Reads and sums (up to) 128 spread-out bytes.
FuzzHash(const uint8_t * const data,size_t size)49*b2055c35SXin Li static WEBP_INLINE uint8_t FuzzHash(const uint8_t* const data, size_t size) {
50*b2055c35SXin Li   uint8_t value = 0;
51*b2055c35SXin Li   size_t incr = size / 128;
52*b2055c35SXin Li   if (!incr) incr = 1;
53*b2055c35SXin Li   for (size_t i = 0; i < size; i += incr) value += data[i];
54*b2055c35SXin Li   return value;
55*b2055c35SXin Li }
56*b2055c35SXin Li 
57*b2055c35SXin Li //------------------------------------------------------------------------------
58*b2055c35SXin Li // Extract an integer in [0, max_value].
59*b2055c35SXin Li 
Extract(uint32_t max_value,const uint8_t data[],size_t size,uint32_t * const bit_pos)60*b2055c35SXin Li static WEBP_INLINE uint32_t Extract(uint32_t max_value,
61*b2055c35SXin Li                                     const uint8_t data[], size_t size,
62*b2055c35SXin Li                                     uint32_t* const bit_pos) {
63*b2055c35SXin Li   uint32_t v = 0;
64*b2055c35SXin Li   uint32_t range = 1;
65*b2055c35SXin Li   while (*bit_pos < 8 * size && range <= max_value) {
66*b2055c35SXin Li     const uint8_t mask = 1u << (*bit_pos & 7);
67*b2055c35SXin Li     v = (v << 1) | !!(data[*bit_pos >> 3] & mask);
68*b2055c35SXin Li     range <<= 1;
69*b2055c35SXin Li     ++*bit_pos;
70*b2055c35SXin Li   }
71*b2055c35SXin Li   return v % (max_value + 1);
72*b2055c35SXin Li }
73*b2055c35SXin Li 
74*b2055c35SXin Li //------------------------------------------------------------------------------
75*b2055c35SXin Li // Some functions to override VP8GetCPUInfo and disable some optimizations.
76*b2055c35SXin Li 
77*b2055c35SXin Li #ifdef __cplusplus
78*b2055c35SXin Li extern "C" VP8CPUInfo VP8GetCPUInfo;
79*b2055c35SXin Li #else
80*b2055c35SXin Li extern VP8CPUInfo VP8GetCPUInfo;
81*b2055c35SXin Li #endif
82*b2055c35SXin Li static VP8CPUInfo GetCPUInfo;
83*b2055c35SXin Li 
GetCPUInfoNoSSE41(CPUFeature feature)84*b2055c35SXin Li static WEBP_INLINE int GetCPUInfoNoSSE41(CPUFeature feature) {
85*b2055c35SXin Li   if (feature == kSSE4_1 || feature == kAVX) return 0;
86*b2055c35SXin Li   return GetCPUInfo(feature);
87*b2055c35SXin Li }
88*b2055c35SXin Li 
GetCPUInfoNoAVX(CPUFeature feature)89*b2055c35SXin Li static WEBP_INLINE int GetCPUInfoNoAVX(CPUFeature feature) {
90*b2055c35SXin Li   if (feature == kAVX) return 0;
91*b2055c35SXin Li   return GetCPUInfo(feature);
92*b2055c35SXin Li }
93*b2055c35SXin Li 
GetCPUInfoForceSlowSSSE3(CPUFeature feature)94*b2055c35SXin Li static WEBP_INLINE int GetCPUInfoForceSlowSSSE3(CPUFeature feature) {
95*b2055c35SXin Li   if (feature == kSlowSSSE3 && GetCPUInfo(kSSE3)) {
96*b2055c35SXin Li     return 1;  // we have SSE3 -> force SlowSSSE3
97*b2055c35SXin Li   }
98*b2055c35SXin Li   return GetCPUInfo(feature);
99*b2055c35SXin Li }
100*b2055c35SXin Li 
GetCPUInfoOnlyC(CPUFeature feature)101*b2055c35SXin Li static WEBP_INLINE int GetCPUInfoOnlyC(CPUFeature feature) {
102*b2055c35SXin Li   (void)feature;
103*b2055c35SXin Li   return 0;
104*b2055c35SXin Li }
105*b2055c35SXin Li 
ExtractAndDisableOptimizations(VP8CPUInfo default_VP8GetCPUInfo,const uint8_t data[],size_t size,uint32_t * const bit_pos)106*b2055c35SXin Li static WEBP_INLINE void ExtractAndDisableOptimizations(
107*b2055c35SXin Li     VP8CPUInfo default_VP8GetCPUInfo, const uint8_t data[], size_t size,
108*b2055c35SXin Li     uint32_t* const bit_pos) {
109*b2055c35SXin Li   GetCPUInfo = default_VP8GetCPUInfo;
110*b2055c35SXin Li   const VP8CPUInfo kVP8CPUInfos[5] = {GetCPUInfoOnlyC, GetCPUInfoForceSlowSSSE3,
111*b2055c35SXin Li                                       GetCPUInfoNoSSE41, GetCPUInfoNoAVX,
112*b2055c35SXin Li                                       GetCPUInfo};
113*b2055c35SXin Li   int VP8GetCPUInfo_index = Extract(4, data, size, bit_pos);
114*b2055c35SXin Li   VP8GetCPUInfo = kVP8CPUInfos[VP8GetCPUInfo_index];
115*b2055c35SXin Li }
116*b2055c35SXin Li 
117*b2055c35SXin Li //------------------------------------------------------------------------------
118*b2055c35SXin Li 
ExtractWebPConfig(WebPConfig * const config,const uint8_t data[],size_t size,uint32_t * const bit_pos)119*b2055c35SXin Li static WEBP_INLINE int ExtractWebPConfig(WebPConfig* const config,
120*b2055c35SXin Li                                          const uint8_t data[], size_t size,
121*b2055c35SXin Li                                          uint32_t* const bit_pos) {
122*b2055c35SXin Li   if (config == NULL || !WebPConfigInit(config)) return 0;
123*b2055c35SXin Li   config->lossless = Extract(1, data, size, bit_pos);
124*b2055c35SXin Li   config->quality = Extract(100, data, size, bit_pos);
125*b2055c35SXin Li   config->method = Extract(6, data, size, bit_pos);
126*b2055c35SXin Li   config->image_hint =
127*b2055c35SXin Li       (WebPImageHint)Extract(WEBP_HINT_LAST - 1, data, size, bit_pos);
128*b2055c35SXin Li   config->segments = 1 + Extract(3, data, size, bit_pos);
129*b2055c35SXin Li   config->sns_strength = Extract(100, data, size, bit_pos);
130*b2055c35SXin Li   config->filter_strength = Extract(100, data, size, bit_pos);
131*b2055c35SXin Li   config->filter_sharpness = Extract(7, data, size, bit_pos);
132*b2055c35SXin Li   config->filter_type = Extract(1, data, size, bit_pos);
133*b2055c35SXin Li   config->autofilter = Extract(1, data, size, bit_pos);
134*b2055c35SXin Li   config->alpha_compression = Extract(1, data, size, bit_pos);
135*b2055c35SXin Li   config->alpha_filtering = Extract(2, data, size, bit_pos);
136*b2055c35SXin Li   config->alpha_quality = Extract(100, data, size, bit_pos);
137*b2055c35SXin Li   config->pass = 1 + Extract(9, data, size, bit_pos);
138*b2055c35SXin Li   config->show_compressed = 1;
139*b2055c35SXin Li   config->preprocessing = Extract(2, data, size, bit_pos);
140*b2055c35SXin Li   config->partitions = Extract(3, data, size, bit_pos);
141*b2055c35SXin Li   config->partition_limit = 10 * Extract(10, data, size, bit_pos);
142*b2055c35SXin Li   config->emulate_jpeg_size = Extract(1, data, size, bit_pos);
143*b2055c35SXin Li   config->thread_level = Extract(1, data, size, bit_pos);
144*b2055c35SXin Li   config->low_memory = Extract(1, data, size, bit_pos);
145*b2055c35SXin Li   config->near_lossless = 20 * Extract(5, data, size, bit_pos);
146*b2055c35SXin Li   config->exact = Extract(1, data, size, bit_pos);
147*b2055c35SXin Li   config->use_delta_palette = Extract(1, data, size, bit_pos);
148*b2055c35SXin Li   config->use_sharp_yuv = Extract(1, data, size, bit_pos);
149*b2055c35SXin Li   return WebPValidateConfig(config);
150*b2055c35SXin Li }
151*b2055c35SXin Li 
152*b2055c35SXin Li //------------------------------------------------------------------------------
153*b2055c35SXin Li 
ExtractSourcePicture(WebPPicture * const pic,const uint8_t data[],size_t size,uint32_t * const bit_pos)154*b2055c35SXin Li static WEBP_INLINE int ExtractSourcePicture(WebPPicture* const pic,
155*b2055c35SXin Li                                             const uint8_t data[], size_t size,
156*b2055c35SXin Li                                             uint32_t* const bit_pos) {
157*b2055c35SXin Li   if (pic == NULL) return 0;
158*b2055c35SXin Li 
159*b2055c35SXin Li   // Pick a source picture.
160*b2055c35SXin Li   const uint8_t* kImagesData[] = {
161*b2055c35SXin Li       kImgAlphaData,
162*b2055c35SXin Li       kImgGridData,
163*b2055c35SXin Li       kImgPeakData
164*b2055c35SXin Li   };
165*b2055c35SXin Li   const int kImagesWidth[] = {
166*b2055c35SXin Li       kImgAlphaWidth,
167*b2055c35SXin Li       kImgGridWidth,
168*b2055c35SXin Li       kImgPeakWidth
169*b2055c35SXin Li   };
170*b2055c35SXin Li   const int kImagesHeight[] = {
171*b2055c35SXin Li       kImgAlphaHeight,
172*b2055c35SXin Li       kImgGridHeight,
173*b2055c35SXin Li       kImgPeakHeight
174*b2055c35SXin Li   };
175*b2055c35SXin Li   const size_t kNbImages = sizeof(kImagesData) / sizeof(kImagesData[0]);
176*b2055c35SXin Li   const size_t image_index = Extract(kNbImages - 1, data, size, bit_pos);
177*b2055c35SXin Li   const uint8_t* const image_data = kImagesData[image_index];
178*b2055c35SXin Li   pic->width = kImagesWidth[image_index];
179*b2055c35SXin Li   pic->height = kImagesHeight[image_index];
180*b2055c35SXin Li   pic->argb_stride = pic->width * 4 * sizeof(uint8_t);
181*b2055c35SXin Li 
182*b2055c35SXin Li   // Read the bytes.
183*b2055c35SXin Li   return WebPPictureImportRGBA(pic, image_data, pic->argb_stride);
184*b2055c35SXin Li }
185*b2055c35SXin Li 
186*b2055c35SXin Li //------------------------------------------------------------------------------
187*b2055c35SXin Li 
Max(int a,int b)188*b2055c35SXin Li static WEBP_INLINE int Max(int a, int b) { return ((a < b) ? b : a); }
189*b2055c35SXin Li 
ExtractAndCropOrScale(WebPPicture * const pic,const uint8_t data[],size_t size,uint32_t * const bit_pos)190*b2055c35SXin Li static WEBP_INLINE int ExtractAndCropOrScale(WebPPicture* const pic,
191*b2055c35SXin Li                                              const uint8_t data[], size_t size,
192*b2055c35SXin Li                                              uint32_t* const bit_pos) {
193*b2055c35SXin Li   if (pic == NULL) return 0;
194*b2055c35SXin Li #if !defined(WEBP_REDUCE_SIZE)
195*b2055c35SXin Li   const int alter_input = Extract(1, data, size, bit_pos);
196*b2055c35SXin Li   const int crop_or_scale = Extract(1, data, size, bit_pos);
197*b2055c35SXin Li   const int width_ratio = 1 + Extract(7, data, size, bit_pos);
198*b2055c35SXin Li   const int height_ratio = 1 + Extract(7, data, size, bit_pos);
199*b2055c35SXin Li   if (alter_input) {
200*b2055c35SXin Li     if (crop_or_scale) {
201*b2055c35SXin Li       const uint32_t left_ratio = 1 + Extract(7, data, size, bit_pos);
202*b2055c35SXin Li       const uint32_t top_ratio = 1 + Extract(7, data, size, bit_pos);
203*b2055c35SXin Li       const int cropped_width = Max(1, pic->width / width_ratio);
204*b2055c35SXin Li       const int cropped_height = Max(1, pic->height / height_ratio);
205*b2055c35SXin Li       const int cropped_left = (pic->width - cropped_width) / left_ratio;
206*b2055c35SXin Li       const int cropped_top = (pic->height - cropped_height) / top_ratio;
207*b2055c35SXin Li       return WebPPictureCrop(pic, cropped_left, cropped_top, cropped_width,
208*b2055c35SXin Li                              cropped_height);
209*b2055c35SXin Li     } else {
210*b2055c35SXin Li       const int scaled_width = 1 + (pic->width * width_ratio) / 8;
211*b2055c35SXin Li       const int scaled_height = 1 + (pic->height * height_ratio) / 8;
212*b2055c35SXin Li       return WebPPictureRescale(pic, scaled_width, scaled_height);
213*b2055c35SXin Li     }
214*b2055c35SXin Li   }
215*b2055c35SXin Li #else   // defined(WEBP_REDUCE_SIZE)
216*b2055c35SXin Li   (void)data;
217*b2055c35SXin Li   (void)size;
218*b2055c35SXin Li   (void)bit_pos;
219*b2055c35SXin Li #endif  // !defined(WEBP_REDUCE_SIZE)
220*b2055c35SXin Li   return 1;
221*b2055c35SXin Li }
222*b2055c35SXin Li 
223*b2055c35SXin Li #endif  // WEBP_TESTS_FUZZER_FUZZ_UTILS_H_
224