Coverage Report

Created: 2026-01-10 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libwebp/tests/fuzzer/fuzz_utils.cc
Line
Count
Source
1
// Copyright 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
#include "./fuzz_utils.h"
18
19
#include <algorithm>
20
#include <cassert>
21
#include <cstddef>
22
#include <cstdint>
23
#include <cstdlib>
24
#include <string>
25
#include <string_view>
26
#include <tuple>
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 "webp/decode.h"
34
#include "webp/encode.h"
35
#include "webp/types.h"
36
37
namespace fuzz_utils {
38
39
27.1k
WebPPicture GetSourcePicture(int image_index, bool use_argb) {
40
27.1k
  WebPPicture pic;
41
27.1k
  if (!WebPPictureInit(&pic)) std::abort();
42
27.1k
  pic.use_argb = use_argb;
43
44
  // Pick a source picture.
45
27.1k
  const int kImagesWidth[] = {kImgAlphaWidth, kImgGridWidth, kImgPeakWidth};
46
27.1k
  const int kImagesHeight[] = {kImgAlphaHeight, kImgGridHeight, kImgPeakHeight};
47
27.1k
  const uint8_t* const image_data = kImagesData[image_index];
48
27.1k
  pic.width = kImagesWidth[image_index];
49
27.1k
  pic.height = kImagesHeight[image_index];
50
27.1k
  pic.argb_stride = pic.width * 4 * sizeof(uint8_t);
51
52
  // Read the bytes.
53
27.1k
  if (!WebPPictureImportRGBA(&pic, image_data, pic.argb_stride)) std::abort();
54
27.1k
  return pic;
55
27.1k
}
56
57
//------------------------------------------------------------------------------
58
59
87.6k
int CropOrScale(WebPPicture* const pic, const CropOrScaleParams& params) {
60
87.6k
  if (pic == NULL) return 0;
61
87.6k
#if !defined(WEBP_REDUCE_SIZE)
62
87.6k
  if (params.alter_input) {
63
37.7k
    if (params.crop_or_scale) {
64
7.53k
      const int cropped_width = std::max(1, pic->width / params.width_ratio);
65
7.53k
      const int cropped_height = std::max(1, pic->height / params.height_ratio);
66
7.53k
      const int cropped_left = (pic->width - cropped_width) / params.left_ratio;
67
7.53k
      const int cropped_top = (pic->height - cropped_height) / params.top_ratio;
68
7.53k
      return WebPPictureCrop(pic, cropped_left, cropped_top, cropped_width,
69
7.53k
                             cropped_height);
70
30.1k
    } else {
71
30.1k
      const int scaled_width = 1 + (pic->width * params.width_ratio) / 8;
72
30.1k
      const int scaled_height = 1 + (pic->height * params.height_ratio) / 8;
73
30.1k
      return WebPPictureRescale(pic, scaled_width, scaled_height);
74
30.1k
    }
75
37.7k
  }
76
#else   // defined(WEBP_REDUCE_SIZE)
77
  (void)pic;
78
  (void)params;
79
#endif  // !defined(WEBP_REDUCE_SIZE)
80
49.9k
  return 1;
81
87.6k
}
82
83
extern "C" VP8CPUInfo VP8GetCPUInfo;
84
static VP8CPUInfo GetCPUInfo;
85
86
180k
static WEBP_INLINE int GetCPUInfoNoSSE41(CPUFeature feature) {
87
180k
  if (feature == kSSE4_1 || feature == kAVX) return 0;
88
106k
  return GetCPUInfo(feature);
89
180k
}
90
91
152k
static WEBP_INLINE int GetCPUInfoNoAVX(CPUFeature feature) {
92
152k
  if (feature == kAVX) return 0;
93
152k
  return GetCPUInfo(feature);
94
152k
}
95
96
166k
static WEBP_INLINE int GetCPUInfoForceSlowSSSE3(CPUFeature feature) {
97
166k
  if (feature == kSlowSSSE3 && GetCPUInfo(kSSE3)) {
98
4.99k
    return 1;  // we have SSE3 -> force SlowSSSE3
99
4.99k
  }
100
161k
  return GetCPUInfo(feature);
101
166k
}
102
103
185k
static WEBP_INLINE int GetCPUInfoOnlyC(CPUFeature feature) {
104
185k
  (void)feature;
105
185k
  return 0;
106
185k
}
107
108
87.6k
void SetOptimization(VP8CPUInfo default_VP8GetCPUInfo, uint32_t index) {
109
87.6k
  assert(index <= kMaxOptimizationIndex);
110
87.6k
  GetCPUInfo = default_VP8GetCPUInfo;
111
87.6k
  const VP8CPUInfo kVP8CPUInfos[kMaxOptimizationIndex + 1] = {
112
87.6k
      GetCPUInfoOnlyC, GetCPUInfoForceSlowSSSE3, GetCPUInfoNoSSE41,
113
87.6k
      GetCPUInfoNoAVX, GetCPUInfo};
114
87.6k
  VP8GetCPUInfo = kVP8CPUInfos[index];
115
87.6k
}
116
117
//------------------------------------------------------------------------------
118
119
0
std::vector<std::string> ReadFilesFromDirectory(std::string_view dir) {
120
0
  std::vector<std::tuple<std::string>> tuples =
121
0
      fuzztest::ReadFilesFromDirectory(dir);
122
0
  std::vector<std::string> strings(tuples.size());
123
0
  for (size_t i = 0; i < tuples.size(); ++i) {
124
0
    using std::swap;
125
0
    swap(std::get<0>(tuples[i]), strings[i]);
126
0
  }
127
0
  return strings;
128
0
}
129
130
//------------------------------------------------------------------------------
131
// The code in this section is copied from
132
// https://github.com/webmproject/sjpeg/blob/
133
//                1c025b3dbc2246de3e1d7c287970f1a01291800f/src/jpeg_tools.cc#L47
134
// (same license as this file).
135
136
namespace {
137
// Constants below are marker codes defined in JPEG spec
138
// ISO/IEC 10918-1 : 1993(E) Table B.1
139
// See also: http://www.w3.org/Graphics/JPEG/itu-t81.pdf
140
141
12.1k
#define M_SOF0 0xffc0
142
5.73k
#define M_SOF1 0xffc1
143
144
10.0k
const uint8_t* GetSOFData(const uint8_t* src, int size) {
145
10.0k
  if (src == NULL) return NULL;
146
10.0k
  const uint8_t* const end = src + size - 8;  // 8 bytes of safety, for marker
147
10.0k
  src += 2;                                   // skip M_SOI
148
8.56M
  for (; src < end && *src != 0xff; ++src) {  /* search first 0xff marker */
149
8.55M
  }
150
15.6k
  while (src < end) {
151
6.05k
    const uint32_t marker = static_cast<uint32_t>((src[0] << 8) | src[1]);
152
6.05k
    if (marker == M_SOF0 || marker == M_SOF1) return src;
153
5.60k
    const size_t s = 2 + ((src[2] << 8) | src[3]);
154
5.60k
    src += s;
155
5.60k
  }
156
9.56k
  return NULL;  // No SOF marker found
157
10.0k
}
158
159
bool SjpegDimensions(const uint8_t* src0, size_t size, int* width, int* height,
160
10.0k
                     int* is_yuv420) {
161
10.0k
  if (width == NULL || height == NULL) return false;
162
10.0k
  const uint8_t* src = GetSOFData(src0, size);
163
10.0k
  const size_t left_over = size - (src - src0);
164
10.0k
  if (src == NULL || left_over < 8 + 3 * 1) return false;
165
449
  if (height != NULL) *height = (src[5] << 8) | src[6];
166
449
  if (width != NULL) *width = (src[7] << 8) | src[8];
167
449
  if (is_yuv420 != NULL) {
168
449
    const size_t nb_comps = src[9];
169
449
    *is_yuv420 = (nb_comps == 3);
170
449
    if (left_over < 11 + 3 * nb_comps) return false;
171
436
    for (int c = 0; *is_yuv420 && c < 3; ++c) {
172
8
      const int expected_dim = (c == 0 ? 0x22 : 0x11);
173
8
      *is_yuv420 &= (src[11 + c * 3] == expected_dim);
174
8
    }
175
428
  }
176
428
  return true;
177
449
}
178
}  // namespace
179
180
//------------------------------------------------------------------------------
181
182
10.0k
bool IsImageTooBig(const uint8_t* data, size_t size) {
183
10.0k
  int width, height, components;
184
10.0k
  if (SjpegDimensions(data, size, &width, &height, &components) ||
185
9.62k
      WebPGetInfo(data, size, &width, &height)) {
186
    // Look at the number of 8x8px blocks rather than the overall pixel count
187
    // when comparing to memory and duration thresholds.
188
6.64k
    const size_t ceiled_width = ((size_t)width + 7) / 8 * 8;
189
6.64k
    const size_t ceiled_height = ((size_t)height + 7) / 8 * 8;
190
    // Threshold to avoid out-of-memory and timeout issues.
191
    // The threshold is arbitrary but below the fuzzer limit of 2 GB.
192
    // The value cannot be 2 GB because of the added memory by MSAN.
193
6.64k
    if (ceiled_width * ceiled_height > kFuzzPxLimit) return true;
194
6.64k
  }
195
9.98k
  return false;
196
10.0k
}
197
198
}  // namespace fuzz_utils