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;
32  int fuzz_size;
33 } IOContext;
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 io_read(void *opaque, uint8_t *buf, int buf_size)
44 {
45  IOContext *c = opaque;
46  int size = FFMIN(buf_size, c->fuzz_size);
47 
48  if (!c->fuzz_size) {
49  c->filesize = FFMIN(c->pos, c->filesize);
50  return AVERROR_EOF;
51  }
52  if (c->pos > INT64_MAX - size)
53  return AVERROR(EIO);
54 
55  memcpy(buf, c->fuzz, size);
56  c->fuzz += size;
57  c->fuzz_size -= size;
58  c->pos += size;
59  c->filesize = FFMAX(c->filesize, c->pos);
60 
61  return size;
62 }
63 
64 static int64_t io_seek(void *opaque, int64_t offset, int whence)
65 {
66  IOContext *c = opaque;
67 
68  if (whence == SEEK_CUR) {
69  if (offset > INT64_MAX - c->pos)
70  return -1;
71  offset += c->pos;
72  } else if (whence == SEEK_END) {
73  if (offset > INT64_MAX - c->filesize)
74  return -1;
75  offset += c->filesize;
76  } else if (whence == AVSEEK_SIZE) {
77  return c->filesize;
78  }
79  if (offset < 0 || offset > c->filesize)
80  return -1;
81  if (IO_FLAT) {
82  c->fuzz += offset - c->pos;
83  c->fuzz_size -= offset - c->pos;
84  }
85  c->pos = offset;
86  return 0;
87 }
88 
89 // Ensure we don't loop forever
90 const uint32_t maxiteration = 8096;
91 const int maxblocks= 100000;
92 
93 static const uint64_t FUZZ_TAG = 0x4741542D5A5A5546ULL;
94 
95 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
96  const uint64_t fuzz_tag = FUZZ_TAG;
97  uint32_t it = 0;
99  AVPacket pkt;
100  char filename[1025] = {0};
101  AVIOContext *fuzzed_pb = NULL;
102  uint8_t *io_buffer;
103  int io_buffer_size = 32768;
104  int64_t filesize = size;
105  IOContext opaque;
106  static int c;
107  int seekable = 0;
108  int ret;
109  AVInputFormat *fmt = NULL;
110 #ifdef FFMPEG_DEMUXER
111 #define DEMUXER_SYMBOL0(DEMUXER) ff_##DEMUXER##_demuxer
112 #define DEMUXER_SYMBOL(DEMUXER) DEMUXER_SYMBOL0(DEMUXER)
113  extern AVInputFormat DEMUXER_SYMBOL(FFMPEG_DEMUXER);
114  fmt = &DEMUXER_SYMBOL(FFMPEG_DEMUXER);
115 #endif
116 
117  if (!c) {
119  c=1;
120  }
121 
122  if (!avfmt)
123  error("Failed avformat_alloc_context()");
124 
125  if (IO_FLAT) {
126  seekable = 1;
127  io_buffer_size = size;
128  } else if (size > 2048) {
129  int flags;
130  char extension[64];
131 
132  GetByteContext gbc;
133  memcpy (filename, data + size - 1024, 1024);
134  bytestream2_init(&gbc, data + size - 2048, 1024);
135  size -= 2048;
136 
137  io_buffer_size = bytestream2_get_le32(&gbc) & 0xFFFFFFF;
138  flags = bytestream2_get_byte(&gbc);
139  seekable = flags & 1;
140  filesize = bytestream2_get_le64(&gbc) & 0x7FFFFFFFFFFFFFFF;
141 
142  if ((flags & 2) && strlen(filename) < sizeof(filename) / 2) {
143  const AVInputFormat *avif = NULL;
144  void *avif_iter = NULL;
145  int avif_count = 0;
146  while ((avif = av_demuxer_iterate(&avif_iter))) {
147  if (avif->extensions)
148  avif_count ++;
149  }
150  avif_count = bytestream2_get_le32(&gbc) % avif_count;
151 
152  avif_iter = NULL;
153  while ((avif = av_demuxer_iterate(&avif_iter))) {
154  if (avif->extensions)
155  if (!avif_count--)
156  break;
157  }
158  av_strlcpy(extension, avif->extensions, sizeof(extension));
159  if (strchr(extension, ','))
160  *strchr(extension, ',') = 0;
161  av_strlcatf(filename, sizeof(filename), ".%s", extension);
162  }
163  }
164 
165  if (!io_buffer_size || size / io_buffer_size > maxblocks)
166  io_buffer_size = size;
167 
168  io_buffer = av_malloc(io_buffer_size);
169  if (!io_buffer)
170  error("Failed to allocate io_buffer");
171 
172  opaque.filesize = filesize;
173  opaque.pos = 0;
174  opaque.fuzz = data;
175  opaque.fuzz_size= size;
176  fuzzed_pb = avio_alloc_context(io_buffer, io_buffer_size, 0, &opaque,
177  io_read, NULL, seekable ? io_seek : NULL);
178  if (!fuzzed_pb)
179  error("avio_alloc_context failed");
180 
181  avfmt->pb = fuzzed_pb;
182 
183  ret = avformat_open_input(&avfmt, filename, fmt, NULL);
184  if (ret < 0) {
185  av_freep(&fuzzed_pb->buffer);
186  av_freep(&fuzzed_pb);
187  avformat_free_context(avfmt);
188  return 0;
189  }
190 
191  ret = avformat_find_stream_info(avfmt, NULL);
192 
193  av_init_packet(&pkt);
194 
195  //TODO, test seeking
196 
197  for(it = 0; it < maxiteration; it++) {
198  ret = av_read_frame(avfmt, &pkt);
199  if (ret < 0)
200  break;
201  av_packet_unref(&pkt);
202  }
203 end:
204  av_freep(&fuzzed_pb->buffer);
205  avio_context_free(&fuzzed_pb);
206  avformat_close_input(&avfmt);
207 
208  return 0;
209 }
#define NULL
Definition: coverity.c:32
Bytestream IO Context.
Definition: avio.h:161
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
void av_log_set_level(int level)
Set the log level.
Definition: log.c:440
const uint32_t maxiteration
unsigned char * buffer
Start of the buffer.
Definition: avio.h:226
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:137
int avformat_open_input(AVFormatContext **ps, const char *url, ff_const59 AVInputFormat *fmt, AVDictionary **options)
Open an input stream and read the header.
Definition: utils.c:500
static AVPacket pkt
static int io_read(void *opaque, uint8_t *buf, int buf_size)
Format I/O context.
Definition: avformat.h:1239
uint8_t
#define av_malloc(s)
#define AV_LOG_PANIC
Something went really wrong and we will crash now.
Definition: log.h:181
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
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:92
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
static const uint64_t FUZZ_TAG
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition: options.c:211
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
#define AVERROR_EOF
End of file.
Definition: error.h:55
ptrdiff_t size
Definition: opengl_enc.c:100
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:138
simple assert() macros that are a bit more flexible than ISO C assert().
#define FFMAX(a, b)
Definition: common.h:94
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:83
#define FFMIN(a, b)
Definition: common.h:96
int64_t filesize
const AVInputFormat * av_demuxer_iterate(void **opaque)
Iterate over all registered demuxers.
Definition: allformats.c:552
uint8_t * fuzz
Libavcodec external API header.
AVIOContext * pb
I/O context.
Definition: avformat.h:1281
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:606
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:101
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: utils.c:4382
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
Definition: utils.c:1712
#define flags(name, subs,...)
Definition: cbs_av1.c:560
const char * extensions
If extensions are defined, then no probe is done.
Definition: avformat.h:673
Main libavformat public API header.
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
Read packets of a media file to get stream information.
Definition: utils.c:3547
void avio_context_free(AVIOContext **s)
Free the supplied IO context and everything associated with it.
Definition: aviobuf.c:155
void av_init_packet(AVPacket *pkt)
Initialize optional fields of a packet with default values.
Definition: avpacket.c:35
#define AVSEEK_SIZE
ORing this as the "whence" parameter to a seek function causes it to return the filesize without seek...
Definition: avio.h:531
void avformat_close_input(AVFormatContext **s)
Close an opened input AVFormatContext.
Definition: utils.c:4425
static void error(const char *err)
#define av_freep(p)
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
This structure stores compressed data.
Definition: packet.h:340
static int64_t io_seek(void *opaque, int64_t offset, int whence)
const int maxblocks