go-libwebp

Experimental translation from libwebp to Go source.
Log | Files | Refs | README | LICENSE

fuzz_utils.h (7837B)


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