1 // Copyright 2019 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <fuzzer/FuzzedDataProvider.h>
6 #include <stddef.h>
7 #include <stdint.h>
8 #include <random>
9
10 #include "third_party/libyuv/include/libyuv.h"
11
FillBufferWithRandomData(uint8_t * dst,size_t len,std::minstd_rand0 rng)12 void FillBufferWithRandomData(uint8_t* dst, size_t len, std::minstd_rand0 rng) {
13 size_t i;
14 for (i = 0; i + 3 < len; i += 4) {
15 *reinterpret_cast<uint32_t*>(dst) = rng();
16 dst += 4;
17 }
18 for (; i < len; ++i) {
19 *dst++ = rng();
20 }
21 }
22
Scale(bool is420,int src_width,int src_height,int dst_width,int dst_height,int filter_num,std::string seed_str)23 static void Scale(bool is420,
24 int src_width,
25 int src_height,
26 int dst_width,
27 int dst_height,
28 int filter_num,
29 std::string seed_str) {
30 int src_width_uv, src_height_uv;
31 if (is420) {
32 src_width_uv = (std::abs(src_width) + 1) >> 1;
33 src_height_uv = (std::abs(src_height) + 1) >> 1;
34 } else {
35 src_width_uv = (std::abs(src_width));
36 src_height_uv = (std::abs(src_height));
37 }
38
39 size_t src_y_plane_size = (std::abs(src_width)) * (std::abs(src_height));
40 size_t src_uv_plane_size = (src_width_uv) * (src_height_uv);
41
42 int src_stride_y = std::abs(src_width);
43 int src_stride_uv = src_width_uv;
44
45 uint8_t* src_y = reinterpret_cast<uint8_t*>(malloc(src_y_plane_size));
46 uint8_t* src_u = reinterpret_cast<uint8_t*>(malloc(src_uv_plane_size));
47 uint8_t* src_v = reinterpret_cast<uint8_t*>(malloc(src_uv_plane_size));
48
49 uint16_t* p_src_y_16 =
50 reinterpret_cast<uint16_t*>(malloc(src_y_plane_size * 2));
51 uint16_t* p_src_u_16 =
52 reinterpret_cast<uint16_t*>(malloc(src_uv_plane_size * 2));
53 uint16_t* p_src_v_16 =
54 reinterpret_cast<uint16_t*>(malloc(src_uv_plane_size * 2));
55
56 std::seed_seq seed(seed_str.begin(), seed_str.end());
57 std::minstd_rand0 rng(seed);
58
59 FillBufferWithRandomData(src_y, src_y_plane_size, rng);
60 FillBufferWithRandomData(src_u, src_uv_plane_size, rng);
61 FillBufferWithRandomData(src_v, src_uv_plane_size, rng);
62
63 for (size_t i = 0; i < src_y_plane_size; ++i) {
64 p_src_y_16[i] = src_y[i];
65 }
66 for (size_t i = 0; i < src_uv_plane_size; ++i) {
67 p_src_u_16[i] = src_u[i];
68 p_src_v_16[i] = src_v[i];
69 }
70
71 int dst_width_uv, dst_height_uv;
72 if (is420) {
73 dst_width_uv = (dst_width + 1) >> 1;
74 dst_height_uv = (dst_height + 1) >> 1;
75 } else {
76 dst_width_uv = dst_width;
77 dst_height_uv = dst_height;
78 }
79
80 size_t dst_y_plane_size = (dst_width) * (dst_height);
81 size_t dst_uv_plane_size = (dst_width_uv) * (dst_height_uv);
82
83 int dst_stride_y = dst_width;
84 int dst_stride_uv = dst_width_uv;
85
86 uint8_t* dst_y_c = reinterpret_cast<uint8_t*>(malloc(dst_y_plane_size));
87 uint8_t* dst_u_c = reinterpret_cast<uint8_t*>(malloc(dst_uv_plane_size));
88 uint8_t* dst_v_c = reinterpret_cast<uint8_t*>(malloc(dst_uv_plane_size));
89
90 uint16_t* p_dst_y_16 =
91 reinterpret_cast<uint16_t*>(malloc(dst_y_plane_size * 2));
92 uint16_t* p_dst_u_16 =
93 reinterpret_cast<uint16_t*>(malloc(dst_uv_plane_size * 2));
94 uint16_t* p_dst_v_16 =
95 reinterpret_cast<uint16_t*>(malloc(dst_uv_plane_size * 2));
96
97 if (is420) {
98 I420Scale(src_y, src_stride_y, src_u, src_stride_uv, src_v, src_stride_uv,
99 src_width, src_height, dst_y_c, dst_stride_y, dst_u_c,
100 dst_stride_uv, dst_v_c, dst_stride_uv, dst_width, dst_height,
101 static_cast<libyuv::FilterMode>(filter_num));
102
103 I420Scale_16(p_src_y_16, src_stride_y, p_src_u_16, src_stride_uv,
104 p_src_v_16, src_stride_uv, src_width, src_height, p_dst_y_16,
105 dst_stride_y, p_dst_u_16, dst_stride_uv, p_dst_v_16,
106 dst_stride_uv, dst_width, dst_height,
107 static_cast<libyuv::FilterMode>(filter_num));
108 } else {
109 I444Scale(src_y, src_stride_y, src_u, src_stride_uv, src_v, src_stride_uv,
110 src_width, src_height, dst_y_c, dst_stride_y, dst_u_c,
111 dst_stride_uv, dst_v_c, dst_stride_uv, dst_width, dst_height,
112 static_cast<libyuv::FilterMode>(filter_num));
113
114 I444Scale_16(p_src_y_16, src_stride_y, p_src_u_16, src_stride_uv,
115 p_src_v_16, src_stride_uv, src_width, src_height, p_dst_y_16,
116 dst_stride_y, p_dst_u_16, dst_stride_uv, p_dst_v_16,
117 dst_stride_uv, dst_width, dst_height,
118 static_cast<libyuv::FilterMode>(filter_num));
119 }
120
121 free(src_y);
122 free(src_u);
123 free(src_v);
124
125 free(p_src_y_16);
126 free(p_src_u_16);
127 free(p_src_v_16);
128
129 free(dst_y_c);
130 free(dst_u_c);
131 free(dst_v_c);
132
133 free(p_dst_y_16);
134 free(p_dst_u_16);
135 free(p_dst_v_16);
136 }
137
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)138 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
139 FuzzedDataProvider provider(data, size);
140
141 // Limit width and height for performance.
142 int src_width = provider.ConsumeIntegralInRange<int>(1, 256);
143 int src_height = provider.ConsumeIntegralInRange<int>(1, 256);
144
145 int filter_num =
146 provider.ConsumeIntegralInRange<int>(0, libyuv::FilterMode::kFilterBox);
147
148 int dst_width = provider.ConsumeIntegralInRange<int>(1, 256);
149 int dst_height = provider.ConsumeIntegralInRange<int>(1, 256);
150
151 std::string seed = provider.ConsumeRemainingBytesAsString();
152
153 Scale(true, src_width, src_height, dst_width, dst_height, filter_num, seed);
154 Scale(false, src_width, src_height, dst_width, dst_height, filter_num, seed);
155
156 return 0;
157 }
158