Ticket #11691: target_sws_fuzzer1143.c

File target_sws_fuzzer1143.c, 6.6 KB (added by flyfish101, 12 months ago)

fuzz driver

Line 
1/*
2 * Copyright (c) 2024 Michael Niedermayer <michael-ffmpeg@niedermayer.cc>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21
22 #include "config.h"
23#include "libavutil/avassert.h"
24#include "libavutil/avstring.h"
25#include "libavutil/cpu.h"
26#include "libavutil/imgutils.h"
27#include "libavutil/intreadwrite.h"
28#include "libavutil/mem.h"
29#include "libavutil/opt.h"
30
31#include "libavcodec/bytestream.h"
32
33#include "libswscale/swscale.h"
34
35int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
36
37static void error(const char *err)
38{
39 fprintf(stderr, "%s", err);
40 exit(1);
41}
42
43static int alloc_plane(uint8_t *data[AV_VIDEO_MAX_PLANES], int stride[AV_VIDEO_MAX_PLANES], int w, int h, int format, int *hshift, int *vshift)
44{
45 size_t size[AV_VIDEO_MAX_PLANES];
46 ptrdiff_t ptrdiff_stride[AV_VIDEO_MAX_PLANES];
47 int ret = av_image_fill_linesizes(stride, format, w);
48 if (ret < 0)
49 return -1;
50
51 av_assert0(AV_VIDEO_MAX_PLANES == 4); // Some of the libavutil API has 4 hardcoded so this has undefined behaviour if its not 4
52
53 av_pix_fmt_get_chroma_sub_sample(format, hshift, vshift);
54
55 for(int p=0; p<AV_VIDEO_MAX_PLANES; p++) {
56 stride[p] =
57 ptrdiff_stride[p] = FFALIGN(stride[p], 32);
58 }
59 ret = av_image_fill_plane_sizes(size, format, h, ptrdiff_stride);
60 if (ret < 0)
61 return ret;
62
63 for(int p=0; p<AV_VIDEO_MAX_PLANES; p++) {
64 if (size[p]) {
65 data[p] = av_mallocz(size[p] + 32);
66 if (!data[p])
67 return -1;
68 } else
69 data[p] = NULL;
70 }
71 return 0;
72}
73
74static void free_plane(uint8_t *data[AV_VIDEO_MAX_PLANES])
75{
76 for(int p=0; p<AV_VIDEO_MAX_PLANES; p++)
77 av_freep(&data[p]);
78}
79
80static void mapres(unsigned *r0, unsigned *r1) {
81 double d = (double)(*r0*10ll - 9ll*UINT32_MAX) / UINT32_MAX;
82 double a = exp(d) * 16384 / exp(1) ;
83 int ai = (int)round(a);
84 uint64_t maxb = 16384 / ai;
85 *r0 = ai;
86 *r1 = 1 + (*r1 * maxb) / UINT32_MAX;
87}
88
89int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
90 int srcW= 48, srcH = 48;
91 int dstW= 48, dstH = 48;
92 int srcHShift, srcVShift;
93 int dstHShift, dstVShift;
94 unsigned flags = 1;
95 int srcStride[AV_VIDEO_MAX_PLANES] = {0};
96 int dstStride[AV_VIDEO_MAX_PLANES] = {0};
97 int ret;
98 const uint8_t *end = data + size;
99 enum AVPixelFormat srcFormat = AV_PIX_FMT_YUV420P;
100 enum AVPixelFormat dstFormat = AV_PIX_FMT_YUV420P;
101 uint8_t *src[AV_VIDEO_MAX_PLANES] = { 0 };
102 uint8_t *dst[AV_VIDEO_MAX_PLANES] = { 0 };
103 struct SwsContext *sws = NULL;
104 const AVPixFmtDescriptor *desc_src, *desc_dst;
105
106 if (size > 128) {
107 GetByteContext gbc;
108 int64_t flags64;
109
110 size -= 128;
111 bytestream2_init(&gbc, data + size, 128);
112 srcW = bytestream2_get_le32(&gbc);
113 srcH = bytestream2_get_le32(&gbc);
114 dstW = bytestream2_get_le32(&gbc);
115 dstH = bytestream2_get_le32(&gbc);
116
117 mapres(&srcW, &srcH);
118 mapres(&dstW, &dstH);
119
120 flags = bytestream2_get_le32(&gbc);
121
122 unsigned mask = flags & (SWS_POINT |
123 SWS_AREA |
124 SWS_BILINEAR |
125 SWS_FAST_BILINEAR |
126 SWS_BICUBIC |
127 SWS_X |
128 SWS_GAUSS |
129 SWS_LANCZOS |
130 SWS_SINC |
131 SWS_SPLINE |
132 SWS_BICUBLIN);
133 mask &= flags;
134 if (mask && (mask & (mask -1)))
135 return 0; // multiple scalers are set, not possible
136
137 srcFormat = bytestream2_get_le32(&gbc) % AV_PIX_FMT_NB;
138 dstFormat = bytestream2_get_le32(&gbc) % AV_PIX_FMT_NB;
139
140 flags64 = bytestream2_get_le64(&gbc);
141 if (flags64 & 0x10)
142 av_force_cpu_flags(0);
143
144 if (av_image_check_size(srcW, srcH, srcFormat, NULL) < 0)
145 srcW = srcH = 23;
146 if (av_image_check_size(dstW, dstH, dstFormat, NULL) < 0)
147 dstW = dstH = 23;
148 //TODO alphablend
149 }
150
151 desc_src = av_pix_fmt_desc_get(srcFormat);
152 desc_dst = av_pix_fmt_desc_get(dstFormat);
153
154 fprintf(stderr, "%d x %d %s -> %d x %d %s\n", srcW, srcH, desc_src->name, dstW, dstH, desc_dst->name);
155
156 ret = alloc_plane(src, srcStride, srcW, srcH, srcFormat, &srcHShift, &srcVShift);
157 if (ret < 0)
158 goto end;
159
160 ret = alloc_plane(dst, dstStride, dstW, dstH, dstFormat, &dstHShift, &dstVShift);
161 if (ret < 0)
162 goto end;
163
164 for(int p=0; p<AV_VIDEO_MAX_PLANES; p++) {
165 int psize = srcStride[p] * AV_CEIL_RSHIFT(srcH, (p == 1 || p == 2) ? srcVShift : 0);
166 if (psize > size)
167 psize = size;
168 if (psize) {
169 memcpy(src[p], data, psize);
170 data += psize;
171 size -= psize;
172 }
173 }
174
175 sws = sws_alloc_context();
176 if (!sws)
177 error("Failed sws allocation");
178
179 av_opt_set_int(sws, "sws_flags", flags, 0);
180 av_opt_set_int(sws, "srcw", srcW, 0);
181 av_opt_set_int(sws, "srch", srcH, 0);
182 av_opt_set_int(sws, "dstw", dstW, 0);
183 av_opt_set_int(sws, "dsth", dstH, 0);
184 av_opt_set_int(sws, "src_format", srcFormat, 0);
185 av_opt_set_int(sws, "dst_format", dstFormat, 0);
186 av_opt_set(sws, "alphablend", "none", 0);
187
188 ret = sws_init_context(sws, NULL, NULL);
189 if (ret < 0)
190 goto end;
191
192 // --- START MODIFICATION ---
193 // Process a slice of the frame with sliceY > 0 to satisfy scale_dst
194 int sliceY = 1; // Start at y=1 (non-zero to trigger dstSliceY > 0)
195 int sliceH = dstH / 2; // Process half the frame height
196 if (sliceH > 0) {
197 sws_scale(sws, (const uint8_t * const*)src, srcStride, sliceY, sliceH, dst, dstStride);
198 }
199 // --- END MODIFICATION ---
200
201end:
202 sws_freeContext(sws);
203
204 free_plane(src);
205 free_plane(dst);
206
207 return 0;
208}