FFmpeg
target_sws_fuzzer.c
Go to the documentation of this file.
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 #include "config.h"
22 #include "libavutil/avassert.h"
23 #include "libavutil/avstring.h"
24 #include "libavutil/cpu.h"
25 #include "libavutil/imgutils.h"
26 #include "libavutil/intreadwrite.h"
27 #include "libavutil/mem.h"
28 #include "libavutil/opt.h"
29 
30 #include "libavcodec/bytestream.h"
31 
32 #include "libswscale/swscale.h"
33 
34 
35 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
36 
37 static void error(const char *err)
38 {
39  fprintf(stderr, "%s", err);
40  exit(1);
41 }
42 
43 static 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];
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 
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 
74 static 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 
80 static 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 
89 int 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 |
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)
143 
145  srcW = srcH = 23;
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 
165  for(int p=0; p<AV_VIDEO_MAX_PLANES; p++) {
166  int psize = srcStride[p] * AV_CEIL_RSHIFT(srcH, (p == 1 || p == 2) ? srcVShift : 0);
167  if (psize > size)
168  psize = size;
169  if (psize) {
170  memcpy(src[p], data, psize);
171  data += psize;
172  size -= psize;
173  }
174  }
175 
176  sws = sws_alloc_context();
177  if (!sws)
178  error("Failed sws allocation");
179 
180  av_opt_set_int(sws, "sws_flags", flags, 0);
181  av_opt_set_int(sws, "srcw", srcW, 0);
182  av_opt_set_int(sws, "srch", srcH, 0);
183  av_opt_set_int(sws, "dstw", dstW, 0);
184  av_opt_set_int(sws, "dsth", dstH, 0);
185  av_opt_set_int(sws, "src_format", srcFormat, 0);
186  av_opt_set_int(sws, "dst_format", dstFormat, 0);
187  av_opt_set(sws, "alphablend", "none", 0);
188 
189  ret = sws_init_context(sws, NULL, NULL);
190  if (ret < 0)
191  goto end;
192 
193  //TODO Slices
194  sws_scale(sws, (const uint8_t * const*)src, srcStride, 0, srcH, dst, dstStride);
195 
196 end:
197  sws_freeContext(sws);
198 
199  free_plane(src);
200  free_plane(dst);
201 
202  return 0;
203 }
av_force_cpu_flags
void av_force_cpu_flags(int arg)
Disables cpu detection and forces the specified flags.
Definition: cpu.c:79
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
opt.h
SwsContext::dstW
int dstW
Width of destination luma/alpha planes.
Definition: swscale_internal.h:514
GetByteContext
Definition: bytestream.h:33
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2965
int64_t
long long int64_t
Definition: coverity.c:34
AV_VIDEO_MAX_PLANES
#define AV_VIDEO_MAX_PLANES
Maximum number of planes in any pixel format.
Definition: pixfmt.h:40
mask
int mask
Definition: mediacodecdec_common.c:154
free_plane
static void free_plane(uint8_t *data[AV_VIDEO_MAX_PLANES])
Definition: target_sws_fuzzer.c:74
w
uint8_t w
Definition: llviddspenc.c:38
AVPixFmtDescriptor::name
const char * name
Definition: pixdesc.h:70
data
const char data[16]
Definition: mxf.c:148
sws_scale
int attribute_align_arg sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[])
swscale wrapper, so we don't need to export the SwsContext.
Definition: swscale.c:1208
AV_PIX_FMT_NB
@ AV_PIX_FMT_NB
number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of...
Definition: pixfmt.h:442
SWS_FAST_BILINEAR
#define SWS_FAST_BILINEAR
Definition: swscale.h:65
SWS_BICUBLIN
#define SWS_BICUBLIN
Definition: swscale.h:71
av_pix_fmt_get_chroma_sub_sample
int av_pix_fmt_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift)
Utility function to access log2_chroma_w log2_chroma_h from the pixel format AVPixFmtDescriptor.
Definition: pixdesc.c:2993
av_opt_set
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
Definition: opt.c:827
SWS_POINT
#define SWS_POINT
Definition: swscale.h:69
avassert.h
SwsContext::srcFormat
enum AVPixelFormat srcFormat
Source pixel format.
Definition: swscale_internal.h:331
av_image_fill_linesizes
int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width)
Fill plane linesizes for an image with pixel format pix_fmt and width width.
Definition: imgutils.c:89
intreadwrite.h
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:60
format
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample format(the sample packing is implied by the sample format) and sample rate. The lists are not just lists
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:73
alloc_plane
static 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)
Definition: target_sws_fuzzer.c:43
SwsContext::dstFormat
enum AVPixelFormat dstFormat
Destination pixel format.
Definition: swscale_internal.h:330
NULL
#define NULL
Definition: coverity.c:32
SWS_SINC
#define SWS_SINC
Definition: swscale.h:73
av_image_fill_plane_sizes
int av_image_fill_plane_sizes(size_t sizes[4], enum AVPixelFormat pix_fmt, int height, const ptrdiff_t linesizes[4])
Fill plane sizes for an image with pixel format pix_fmt and height height.
Definition: imgutils.c:111
sws_alloc_context
struct SwsContext * sws_alloc_context(void)
Allocate an empty SwsContext.
Definition: utils.c:1217
double
double
Definition: af_crystalizer.c:132
exp
int8_t exp
Definition: eval.c:73
av_opt_set_int
int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
Definition: opt.c:872
SWS_X
#define SWS_X
Definition: swscale.h:68
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:83
cpu.h
size
int size
Definition: twinvq_data.h:10344
SwsContext::srcH
int srcH
Height of source luma/alpha planes.
Definition: swscale_internal.h:322
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
SWS_GAUSS
#define SWS_GAUSS
Definition: swscale.h:72
error
static void error(const char *err)
Definition: target_sws_fuzzer.c:37
SWS_SPLINE
#define SWS_SPLINE
Definition: swscale.h:75
SwsContext::srcW
int srcW
Width of source luma/alpha planes.
Definition: swscale_internal.h:321
round
static av_always_inline av_const double round(double x)
Definition: libm.h:444
SWS_LANCZOS
#define SWS_LANCZOS
Definition: swscale.h:74
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:256
stride
#define stride
Definition: h264pred_template.c:537
ret
ret
Definition: filter_design.txt:187
sws_init_context
av_warn_unused_result int sws_init_context(struct SwsContext *sws_context, SwsFilter *srcFilter, SwsFilter *dstFilter)
Initialize the swscaler context sws_context.
Definition: utils.c:2068
sws_freeContext
void sws_freeContext(struct SwsContext *swsContext)
Free the swscaler context swsContext.
Definition: utils.c:2432
mapres
static void mapres(unsigned *r0, unsigned *r1)
Definition: target_sws_fuzzer.c:80
mem.h
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
LLVMFuzzerTestOneInput
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
Definition: target_sws_fuzzer.c:89
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
bytestream.h
imgutils.h
bytestream2_init
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:137
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:482
h
h
Definition: vp9dsp_template.c:2070
avstring.h
av_image_check_size
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
Check if the given dimension of an image is valid, meaning that all bytes of the image can be address...
Definition: imgutils.c:318
SWS_BILINEAR
#define SWS_BILINEAR
Definition: swscale.h:66
SWS_AREA
#define SWS_AREA
Definition: swscale.h:70
SwsContext
Definition: swscale_internal.h:299
SwsContext::dstH
int dstH
Height of destination luma/alpha planes.
Definition: swscale_internal.h:323
SWS_BICUBIC
#define SWS_BICUBIC
Definition: swscale.h:67
src
#define src
Definition: vp8dsp.c:248
swscale.h