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/opt.h"
28 
29 #include "libavcodec/bytestream.h"
30 
31 #include "libswscale/swscale.h"
32 
33 
34 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
35 
36 static void error(const char *err)
37 {
38  fprintf(stderr, "%s", err);
39  exit(1);
40 }
41 
42 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)
43 {
44  size_t size[AV_VIDEO_MAX_PLANES];
45  ptrdiff_t ptrdiff_stride[AV_VIDEO_MAX_PLANES];
47  if (ret < 0)
48  return -1;
49 
50  av_assert0(AV_VIDEO_MAX_PLANES == 4); // Some of the libavutil API has 4 hardcoded so this has undefined behaviour if its not 4
51 
53 
54  for(int p=0; p<AV_VIDEO_MAX_PLANES; p++) {
55  stride[p] =
56  ptrdiff_stride[p] = FFALIGN(stride[p], 32);
57  }
58  ret = av_image_fill_plane_sizes(size, format, h, ptrdiff_stride);
59  if (ret < 0)
60  return ret;
61 
62  for(int p=0; p<AV_VIDEO_MAX_PLANES; p++) {
63  if (size[p]) {
64  data[p] = av_mallocz(size[p] + 32);
65  if (!data[p])
66  return -1;
67  } else
68  data[p] = NULL;
69  }
70  return 0;
71 }
72 
73 static void free_plane(uint8_t *data[AV_VIDEO_MAX_PLANES])
74 {
75  for(int p=0; p<AV_VIDEO_MAX_PLANES; p++)
76  av_freep(&data[p]);
77 }
78 
79 static void mapres(unsigned *r0, unsigned *r1) {
80  double d = (double)(*r0*10ll - 9ll*UINT32_MAX) / UINT32_MAX;
81  double a = exp(d) * 16384 / exp(1) ;
82  int ai = (int)round(a);
83  uint64_t maxb = 16384 / ai;
84  *r0 = ai;
85  *r1 = 1 + (*r1 * maxb) / UINT32_MAX;
86 }
87 
88 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
89  int srcW= 48, srcH = 48;
90  int dstW= 48, dstH = 48;
91  int srcHShift, srcVShift;
92  int dstHShift, dstVShift;
93  unsigned flags = 1;
94  int srcStride[AV_VIDEO_MAX_PLANES] = {0};
95  int dstStride[AV_VIDEO_MAX_PLANES] = {0};
96  int ret;
97  const uint8_t *end = data + size;
98  enum AVPixelFormat srcFormat = AV_PIX_FMT_YUV420P;
99  enum AVPixelFormat dstFormat = AV_PIX_FMT_YUV420P;
100  uint8_t *src[AV_VIDEO_MAX_PLANES] = { 0 };
101  uint8_t *dst[AV_VIDEO_MAX_PLANES] = { 0 };
102  struct SwsContext *sws = NULL;
103  const AVPixFmtDescriptor *desc_src, *desc_dst;
104 
105  if (size > 128) {
106  GetByteContext gbc;
107  int64_t flags64;
108 
109  size -= 128;
110  bytestream2_init(&gbc, data + size, 128);
111  srcW = bytestream2_get_le32(&gbc);
112  srcH = bytestream2_get_le32(&gbc);
113  dstW = bytestream2_get_le32(&gbc);
114  dstH = bytestream2_get_le32(&gbc);
115 
116  mapres(&srcW, &srcH);
117  mapres(&dstW, &dstH);
118 
119  flags = bytestream2_get_le32(&gbc);
120 
121  unsigned mask = flags & (SWS_POINT |
122  SWS_AREA |
123  SWS_BILINEAR |
125  SWS_BICUBIC |
126  SWS_X |
127  SWS_GAUSS |
128  SWS_LANCZOS |
129  SWS_SINC |
130  SWS_SPLINE |
131  SWS_BICUBLIN);
132  mask &= flags;
133  if (mask && (mask & (mask -1)))
134  return 0; // multiple scalers are set, not possible
135 
136  srcFormat = bytestream2_get_le32(&gbc) % AV_PIX_FMT_NB;
137  dstFormat = bytestream2_get_le32(&gbc) % AV_PIX_FMT_NB;
138 
139  flags64 = bytestream2_get_le64(&gbc);
140  if (flags64 & 0x10)
142 
144  srcW = srcH = 23;
146  dstW = dstH = 23;
147  //TODO alphablend
148  }
149 
150  desc_src = av_pix_fmt_desc_get(srcFormat);
151  desc_dst = av_pix_fmt_desc_get(dstFormat);
152 
153  fprintf(stderr, "%d x %d %s -> %d x %d %s\n", srcW, srcH, desc_src->name, dstW, dstH, desc_dst->name);
154 
155  ret = alloc_plane(src, srcStride, srcW, srcH, srcFormat, &srcHShift, &srcVShift);
156  if (ret < 0)
157  goto end;
158 
159  ret = alloc_plane(dst, dstStride, dstW, dstH, dstFormat, &dstHShift, &dstVShift);
160  if (ret < 0)
161  goto end;
162 
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  //TODO Slices
193  sws_scale(sws, (const uint8_t * const*)src, srcStride, 0, srcH, dst, dstStride);
194 
195 end:
196  sws_freeContext(sws);
197 
198  free_plane(src);
199  free_plane(dst);
200 
201  return 0;
202 }
av_force_cpu_flags
void av_force_cpu_flags(int arg)
Disables cpu detection and forces the specified flags.
Definition: cpu.c:75
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:2962
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
free_plane
static void free_plane(uint8_t *data[AV_VIDEO_MAX_PLANES])
Definition: target_sws_fuzzer.c:73
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:1205
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:2990
av_opt_set
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
Definition: opt.c:738
SWS_POINT
#define SWS_POINT
Definition: swscale.h:69
avassert.h
SwsContext::srcFormat
enum AVPixelFormat srcFormat
Source pixel format.
Definition: swscale_internal.h:331
mask
static const uint16_t mask[17]
Definition: lzw.c:38
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:58
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:42
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:1180
double
double
Definition: af_crystalizer.c:131
exp
int8_t exp
Definition: eval.c:74
av_opt_set_int
int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
Definition: opt.c:789
SWS_X
#define SWS_X
Definition: swscale.h:68
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:36
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:254
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:2036
sws_freeContext
void sws_freeContext(struct SwsContext *swsContext)
Free the swscaler context swsContext.
Definition: utils.c:2425
mapres
static void mapres(unsigned *r0, unsigned *r1)
Definition: target_sws_fuzzer.c:79
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:88
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
d
d
Definition: ffmpeg_filter.c:409
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:2038
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
int
int
Definition: ffmpeg_filter.c:409
SwsContext::dstH
int dstH
Height of destination luma/alpha planes.
Definition: swscale_internal.h:323
SWS_BICUBIC
#define SWS_BICUBIC
Definition: swscale.h:67
swscale.h