FFmpeg
target_dem_fuzzer.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include "config.h"
20 #include "libavutil/avassert.h"
21 #include "libavutil/avstring.h"
22 
23 #include "libavcodec/avcodec.h"
24 #include "libavcodec/bytestream.h"
25 #include "libavformat/avformat.h"
26 
27 
28 typedef struct IOContext {
29  int64_t pos;
30  int64_t filesize;
31  uint8_t *fuzz;
32  int fuzz_size;
33 } IOContext;
34 
35 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
36 
38 static int interrupt_cb(void *ctx)
39 {
41  return interrupt_counter < 0;
42 }
43 
44 static void error(const char *err)
45 {
46  fprintf(stderr, "%s", err);
47  exit(1);
48 }
49 
50 static int io_read(void *opaque, uint8_t *buf, int buf_size)
51 {
52  IOContext *c = opaque;
53  int size = FFMIN(buf_size, c->fuzz_size);
54 
55  if (!c->fuzz_size) {
56  c->filesize = FFMIN(c->pos, c->filesize);
57  return AVERROR_EOF;
58  }
59  if (c->pos > INT64_MAX - size)
60  return AVERROR(EIO);
61 
62  memcpy(buf, c->fuzz, size);
63  c->fuzz += size;
64  c->fuzz_size -= size;
65  c->pos += size;
66  c->filesize = FFMAX(c->filesize, c->pos);
67 
68  return size;
69 }
70 
71 static int64_t io_seek(void *opaque, int64_t offset, int whence)
72 {
73  IOContext *c = opaque;
74 
75  if (whence == SEEK_CUR) {
76  if (offset > INT64_MAX - c->pos)
77  return -1;
78  offset += c->pos;
79  } else if (whence == SEEK_END) {
80  if (offset > INT64_MAX - c->filesize)
81  return -1;
82  offset += c->filesize;
83  } else if (whence == AVSEEK_SIZE) {
84  return c->filesize;
85  }
86  if (offset < 0 || offset > c->filesize)
87  return -1;
88  if (IO_FLAT) {
89  c->fuzz += offset - c->pos;
90  c->fuzz_size -= offset - c->pos;
91  }
92  c->pos = offset;
93  return 0;
94 }
95 
96 // Ensure we don't loop forever
97 const uint32_t maxiteration = 8096;
98 const int maxblocks= 50000;
99 
100 static const uint64_t FUZZ_TAG = 0x4741542D5A5A5546ULL;
101 
102 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
103  const uint64_t fuzz_tag = FUZZ_TAG;
104  uint32_t it = 0;
106  AVPacket *pkt;
107  char filename[1025] = {0};
108  AVIOContext *fuzzed_pb = NULL;
109  uint8_t *io_buffer;
110  int io_buffer_size = 32768;
111  int64_t filesize = size;
112  IOContext opaque;
113  static int c;
114  int seekable = 0;
115  int ret;
116  AVInputFormat *fmt = NULL;
117 #ifdef FFMPEG_DEMUXER
118 #define DEMUXER_SYMBOL0(DEMUXER) ff_##DEMUXER##_demuxer
119 #define DEMUXER_SYMBOL(DEMUXER) DEMUXER_SYMBOL0(DEMUXER)
120  extern AVInputFormat DEMUXER_SYMBOL(FFMPEG_DEMUXER);
121  fmt = &DEMUXER_SYMBOL(FFMPEG_DEMUXER);
122 #endif
123 
124  if (!c) {
126  c=1;
127  }
128 
129  if (!avfmt)
130  error("Failed avformat_alloc_context()");
131 
132  if (IO_FLAT) {
133  seekable = 1;
134  io_buffer_size = size;
135  } else if (size > 2048) {
136  int flags;
137  char extension[64];
138 
139  GetByteContext gbc;
140  memcpy (filename, data + size - 1024, 1024);
141  bytestream2_init(&gbc, data + size - 2048, 1024);
142  size -= 2048;
143 
144  io_buffer_size = bytestream2_get_le32(&gbc) & 0xFFFFFFF;
145  flags = bytestream2_get_byte(&gbc);
146  seekable = flags & 1;
147  filesize = bytestream2_get_le64(&gbc) & 0x7FFFFFFFFFFFFFFF;
148 
149  if ((flags & 2) && strlen(filename) < sizeof(filename) / 2) {
150  const AVInputFormat *avif = NULL;
151  void *avif_iter = NULL;
152  int avif_count = 0;
153  while ((avif = av_demuxer_iterate(&avif_iter))) {
154  if (avif->extensions)
155  avif_count ++;
156  }
157  avif_count = bytestream2_get_le32(&gbc) % avif_count;
158 
159  avif_iter = NULL;
160  while ((avif = av_demuxer_iterate(&avif_iter))) {
161  if (avif->extensions)
162  if (!avif_count--)
163  break;
164  }
165  av_strlcpy(extension, avif->extensions, sizeof(extension));
166  if (strchr(extension, ','))
167  *strchr(extension, ',') = 0;
168  av_strlcatf(filename, sizeof(filename), ".%s", extension);
169  }
170 
171  interrupt_counter = bytestream2_get_le32(&gbc);
173  }
174 
175  // HLS uses a loop with sleep, we thus must breakout or we timeout
176  if (fmt && !strcmp(fmt->name, "hls"))
177  interrupt_counter &= 31;
178 
179  if (!io_buffer_size || size / io_buffer_size > maxblocks)
180  io_buffer_size = size;
181 
182  pkt = av_packet_alloc();
183  if (!pkt)
184  error("Failed to allocate pkt");
185 
186  io_buffer = av_malloc(io_buffer_size);
187  if (!io_buffer)
188  error("Failed to allocate io_buffer");
189 
190  opaque.filesize = filesize;
191  opaque.pos = 0;
192  opaque.fuzz = data;
193  opaque.fuzz_size= size;
194  fuzzed_pb = avio_alloc_context(io_buffer, io_buffer_size, 0, &opaque,
195  io_read, NULL, seekable ? io_seek : NULL);
196  if (!fuzzed_pb)
197  error("avio_alloc_context failed");
198 
199  avfmt->pb = fuzzed_pb;
200 
201  ret = avformat_open_input(&avfmt, filename, fmt, NULL);
202  if (ret < 0) {
203  goto fail;
204  }
205 
207 
208  //TODO, test seeking
209 
210  for(it = 0; it < maxiteration; it++) {
211  ret = av_read_frame(avfmt, pkt);
212  if (ret < 0)
213  break;
215  }
216 
217 fail:
219  av_freep(&fuzzed_pb->buffer);
220  avio_context_free(&fuzzed_pb);
221  avformat_close_input(&avfmt);
222 
223  return 0;
224 
225 }
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:422
IOContext::filesize
int64_t filesize
Definition: target_dem_fuzzer.c:30
AVERROR
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 they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
GetByteContext
Definition: bytestream.h:33
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
AV_LOG_PANIC
#define AV_LOG_PANIC
Something went really wrong and we will crash now.
Definition: log.h:167
avio_context_free
void avio_context_free(AVIOContext **s)
Free the supplied IO context and everything associated with it.
Definition: aviobuf.c:152
IOContext::fuzz
uint8_t * fuzz
Definition: target_dem_fuzzer.c:31
AVSEEK_SIZE
#define AVSEEK_SIZE
ORing this as the "whence" parameter to a seek function causes it to return the filesize without seek...
Definition: avio.h:479
data
const char data[16]
Definition: mxf.c:143
io_seek
static int64_t io_seek(void *opaque, int64_t offset, int whence)
Definition: target_dem_fuzzer.c:71
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
av_read_frame
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
Definition: demux.c:1438
IOContext::pos
int64_t pos
Definition: target_dem_fuzzer.c:29
av_strlcatf
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:104
av_packet_free
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition: avpacket.c:73
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
avformat_close_input
void avformat_close_input(AVFormatContext **s)
Close an opened input AVFormatContext.
Definition: demux.c:368
AVFormatContext::interrupt_callback
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition: avformat.h:1480
io_read
static int io_read(void *opaque, uint8_t *buf, int buf_size)
Definition: target_dem_fuzzer.c:50
fail
#define fail()
Definition: checkasm.h:130
avassert.h
pkt
AVPacket * pkt
Definition: movenc.c:59
AVInputFormat
Definition: avformat.h:656
AVInputFormat::extensions
const char * extensions
If extensions are defined, then no probe is done.
Definition: avformat.h:682
avformat_open_input
int avformat_open_input(AVFormatContext **ps, const char *url, const AVInputFormat *fmt, AVDictionary **options)
Open an input stream and read the header.
Definition: demux.c:220
AVInputFormat::name
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:661
ctx
AVFormatContext * ctx
Definition: movenc.c:48
IOContext::fuzz_size
int fuzz_size
Definition: target_dem_fuzzer.c:32
AVFormatContext
Format I/O context.
Definition: avformat.h:1213
NULL
#define NULL
Definition: coverity.c:32
FUZZ_TAG
static const uint64_t FUZZ_TAG
Definition: target_dem_fuzzer.c:100
AVFormatContext::pb
AVIOContext * pb
I/O context.
Definition: avformat.h:1255
interrupt_cb
static int interrupt_cb(void *ctx)
Definition: target_dem_fuzzer.c:38
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
avformat_find_stream_info
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
Read packets of a media file to get stream information.
Definition: demux.c:2415
AVIOContext
Bytestream IO Context.
Definition: avio.h:162
avformat_alloc_context
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition: options.c:164
size
int size
Definition: twinvq_data.h:10344
av_demuxer_iterate
const AVInputFormat * av_demuxer_iterate(void **opaque)
Iterate over all registered demuxers.
Definition: allformats.c:569
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
av_packet_alloc
AVPacket * av_packet_alloc(void)
Allocate an AVPacket and set its fields to default values.
Definition: avpacket.c:62
av_log_set_level
void av_log_set_level(int level)
Set the log level.
Definition: log.c:442
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
avio_alloc_context
AVIOContext * avio_alloc_context(unsigned char *buffer, int buffer_size, int write_flag, void *opaque, int(*read_packet)(void *opaque, uint8_t *buf, int buf_size), int(*write_packet)(void *opaque, uint8_t *buf, int buf_size), int64_t(*seek)(void *opaque, int64_t offset, int whence))
Allocate and initialize an AVIOContext for buffered I/O.
Definition: aviobuf.c:135
error
static void error(const char *err)
Definition: target_dem_fuzzer.c:44
avcodec.h
ret
ret
Definition: filter_design.txt:187
avformat.h
LLVMFuzzerTestOneInput
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
Definition: target_dem_fuzzer.c:102
interrupt_counter
int64_t interrupt_counter
Definition: target_dem_fuzzer.c:37
it
s EdgeDetect Foobar g libavfilter vf_edgedetect c libavfilter vf_foobar c edit libavfilter and add an entry for foobar following the pattern of the other filters edit libavfilter allfilters and add an entry for foobar following the pattern of the other filters configure make j< whatever > ffmpeg ffmpeg i you should get a foobar png with Lena edge detected That s it
Definition: writing_filters.txt:31
IOContext
Definition: target_dem_fuzzer.c:28
AVIOInterruptCB::callback
int(* callback)(void *)
Definition: avio.h:60
AVIOContext::buffer
unsigned char * buffer
Start of the buffer.
Definition: avio.h:227
AVPacket
This structure stores compressed data.
Definition: packet.h:351
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
bytestream.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:561
av_strlcpy
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition: avstring.c:86
maxblocks
const int maxblocks
Definition: target_dem_fuzzer.c:98
avstring.h
maxiteration
const uint32_t maxiteration
Definition: target_dem_fuzzer.c:97