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 #include "libavutil/mem.h"
23 
24 #include "libavcodec/avcodec.h"
25 #include "libavcodec/bytestream.h"
26 #include "libavformat/avformat.h"
27 #include "libavformat/demux.h"
28 
29 typedef struct IOContext {
32  uint8_t *fuzz;
33  int fuzz_size;
34 } IOContext;
35 
36 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
37 
39 static int interrupt_cb(void *ctx)
40 {
42  return interrupt_counter < 0;
43 }
44 
45 static void error(const char *err)
46 {
47  fprintf(stderr, "%s", err);
48  exit(1);
49 }
50 
51 static int io_read(void *opaque, uint8_t *buf, int buf_size)
52 {
53  IOContext *c = opaque;
54  int size = FFMIN(buf_size, c->fuzz_size);
55 
56  if (!c->fuzz_size) {
57  c->filesize = FFMIN(c->pos, c->filesize);
58  return AVERROR_EOF;
59  }
60  if (c->pos > INT64_MAX - size)
61  return AVERROR(EIO);
62 
63  memcpy(buf, c->fuzz, size);
64  c->fuzz += size;
65  c->fuzz_size -= size;
66  c->pos += size;
67  c->filesize = FFMAX(c->filesize, c->pos);
68 
69  return size;
70 }
71 
72 static int64_t io_seek(void *opaque, int64_t offset, int whence)
73 {
74  IOContext *c = opaque;
75 
76  if (whence == SEEK_CUR) {
77  if (offset > INT64_MAX - c->pos)
78  return -1;
79  offset += c->pos;
80  } else if (whence == SEEK_END) {
81  if (offset > INT64_MAX - c->filesize)
82  return -1;
83  offset += c->filesize;
84  } else if (whence == AVSEEK_SIZE) {
85  return c->filesize;
86  }
87  if (offset < 0 || offset > c->filesize)
88  return -1;
89  if (IO_FLAT) {
90  c->fuzz += offset - c->pos;
91  c->fuzz_size -= offset - c->pos;
92  }
93  c->pos = offset;
94  return 0;
95 }
96 
97 // Ensure we don't loop forever
98 const uint32_t maxiteration = 8096;
99 const int maxblocks= 50000;
100 
101 static const uint64_t FUZZ_TAG = 0x4741542D5A5A5546ULL;
102 
103 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
104  const uint64_t fuzz_tag = FUZZ_TAG;
105  uint32_t it = 0;
107  AVPacket *pkt;
108  char filename[1025] = {0};
109  AVIOContext *fuzzed_pb = NULL;
110  uint8_t *io_buffer;
111  int io_buffer_size = 32768;
113  IOContext opaque;
114  static int c;
115  int seekable = 0;
116  int ret;
117  const AVInputFormat *fmt = NULL;
118 #ifdef FFMPEG_DEMUXER
119 #define DEMUXER_SYMBOL0(DEMUXER) ff_##DEMUXER##_demuxer
120 #define DEMUXER_SYMBOL(DEMUXER) DEMUXER_SYMBOL0(DEMUXER)
121  extern const FFInputFormat DEMUXER_SYMBOL(FFMPEG_DEMUXER);
122  fmt = &DEMUXER_SYMBOL(FFMPEG_DEMUXER).p;
123 #endif
124 
125  if (!c) {
127  c=1;
128  }
129 
130  if (!avfmt)
131  error("Failed avformat_alloc_context()");
132 
133  if (IO_FLAT) {
134  seekable = 1;
135  io_buffer_size = size;
136  } else if (size > 2048) {
137  int flags;
138  char extension[64];
139 
140  GetByteContext gbc;
141  memcpy (filename, data + size - 1024, 1024);
142  bytestream2_init(&gbc, data + size - 2048, 1024);
143  size -= 2048;
144 
145  io_buffer_size = bytestream2_get_le32(&gbc) & 0xFFFFFFF;
146  flags = bytestream2_get_byte(&gbc);
147  seekable = flags & 1;
148  filesize = bytestream2_get_le64(&gbc) & 0x7FFFFFFFFFFFFFFF;
149 
150  if ((flags & 2) && strlen(filename) < sizeof(filename) / 2) {
151  const AVInputFormat *avif = NULL;
152  void *avif_iter = NULL;
153  int avif_count = 0;
154  while ((avif = av_demuxer_iterate(&avif_iter))) {
155  if (avif->extensions)
156  avif_count ++;
157  }
158  avif_count = bytestream2_get_le32(&gbc) % avif_count;
159 
160  avif_iter = NULL;
161  while ((avif = av_demuxer_iterate(&avif_iter))) {
162  if (avif->extensions)
163  if (!avif_count--)
164  break;
165  }
166  av_strlcpy(extension, avif->extensions, sizeof(extension));
167  if (strchr(extension, ','))
168  *strchr(extension, ',') = 0;
169  av_strlcatf(filename, sizeof(filename), ".%s", extension);
170  }
171 
172  interrupt_counter = bytestream2_get_le32(&gbc);
174  }
175 
176  // HLS uses a loop with sleep, we thus must breakout or we timeout
177  if (fmt && !strcmp(fmt->name, "hls"))
178  interrupt_counter &= 31;
179 
180  if (!io_buffer_size || size / io_buffer_size > maxblocks)
181  io_buffer_size = size;
182 
183  pkt = av_packet_alloc();
184  if (!pkt)
185  error("Failed to allocate pkt");
186 
187  io_buffer = av_malloc(io_buffer_size);
188  if (!io_buffer)
189  error("Failed to allocate io_buffer");
190 
191  opaque.filesize = filesize;
192  opaque.pos = 0;
193  opaque.fuzz = data;
194  opaque.fuzz_size= size;
195  fuzzed_pb = avio_alloc_context(io_buffer, io_buffer_size, 0, &opaque,
196  io_read, NULL, seekable ? io_seek : NULL);
197  if (!fuzzed_pb)
198  error("avio_alloc_context failed");
199 
200  avfmt->pb = fuzzed_pb;
201 
202  ret = avformat_open_input(&avfmt, filename, fmt, NULL);
203  if (ret < 0) {
204  goto fail;
205  }
206 
208 
209  //TODO, test seeking
210 
211  for(it = 0; it < maxiteration; it++) {
212  ret = av_read_frame(avfmt, pkt);
213  if (ret < 0)
214  break;
216  }
217 
218 fail:
220  av_freep(&fuzzed_pb->buffer);
221  avio_context_free(&fuzzed_pb);
222  avformat_close_input(&avfmt);
223 
224  return 0;
225 
226 }
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: packet.c:429
IOContext::filesize
int64_t filesize
Definition: target_dem_fuzzer.c:31
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:196
avio_context_free
void avio_context_free(AVIOContext **s)
Free the supplied IO context and everything associated with it.
Definition: aviobuf.c:126
IOContext::fuzz
uint8_t * fuzz
Definition: target_dem_fuzzer.c:32
int64_t
long long int64_t
Definition: coverity.c:34
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, const 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:109
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:468
data
const char data[16]
Definition: mxf.c:149
io_seek
static int64_t io_seek(void *opaque, int64_t offset, int whence)
Definition: target_dem_fuzzer.c:72
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:1547
IOContext::pos
int64_t pos
Definition: target_dem_fuzzer.c:30
av_strlcatf
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:103
av_packet_free
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition: packet.c:74
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:366
AVFormatContext::interrupt_callback
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition: avformat.h:1573
io_read
static int io_read(void *opaque, uint8_t *buf, int buf_size)
Definition: target_dem_fuzzer.c:51
fail
#define fail()
Definition: checkasm.h:193
avassert.h
pkt
AVPacket * pkt
Definition: movenc.c:60
AVInputFormat
Definition: avformat.h:548
AVInputFormat::extensions
const char * extensions
If extensions are defined, then no probe is done.
Definition: avformat.h:574
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:216
AVInputFormat::name
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:553
ctx
AVFormatContext * ctx
Definition: movenc.c:49
IOContext::fuzz_size
int fuzz_size
Definition: target_dem_fuzzer.c:33
AVFormatContext
Format I/O context.
Definition: avformat.h:1300
NULL
#define NULL
Definition: coverity.c:32
FUZZ_TAG
static const uint64_t FUZZ_TAG
Definition: target_dem_fuzzer.c:101
AVFormatContext::pb
AVIOContext * pb
I/O context.
Definition: avformat.h:1342
interrupt_cb
static int interrupt_cb(void *ctx)
Definition: target_dem_fuzzer.c:39
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:2525
AVIOContext
Bytestream IO Context.
Definition: avio.h:160
avformat_alloc_context
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition: options.c:162
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:607
FFInputFormat::p
AVInputFormat p
The public AVInputFormat.
Definition: demux.h:46
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: packet.c:63
filesize
static int64_t filesize(AVIOContext *pb)
Definition: ffmpeg_mux.c:51
av_log_set_level
void av_log_set_level(int level)
Set the log level.
Definition: log.c:447
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
demux.h
error
static void error(const char *err)
Definition: target_dem_fuzzer.c:45
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:103
mem.h
interrupt_counter
int64_t interrupt_counter
Definition: target_dem_fuzzer.c:38
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:29
AVIOInterruptCB::callback
int(* callback)(void *)
Definition: avio.h:60
AVIOContext::buffer
unsigned char * buffer
Start of the buffer.
Definition: avio.h:225
AVPacket
This structure stores compressed data.
Definition: packet.h:516
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
FFInputFormat
Definition: demux.h:42
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:482
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:85
maxblocks
const int maxblocks
Definition: target_dem_fuzzer.c:99
avstring.h
maxiteration
const uint32_t maxiteration
Definition: target_dem_fuzzer.c:98