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 
22 #include "libavcodec/avcodec.h"
23 #include "libavcodec/bytestream.h"
24 #include "libavformat/avformat.h"
25 
26 
27 typedef struct IOContext {
28  int64_t pos;
29  int64_t filesize;
31  int fuzz_size;
32 } IOContext;
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 io_read(void *opaque, uint8_t *buf, int buf_size)
43 {
44  IOContext *c = opaque;
45  int size = FFMIN(buf_size, c->fuzz_size);
46 
47  if (!c->fuzz_size) {
48  c->filesize = FFMIN(c->pos, c->filesize);
49  return AVERROR_EOF;
50  }
51 
52  memcpy(buf, c->fuzz, size);
53  c->fuzz += size;
54  c->fuzz_size -= size;
55  c->pos += size;
56  c->filesize = FFMAX(c->filesize, c->pos);
57 
58  return size;
59 }
60 
61 static int64_t io_seek(void *opaque, int64_t offset, int whence)
62 {
63  IOContext *c = opaque;
64 
65  if (whence == SEEK_CUR) {
66  if (offset > INT64_MAX - c->pos)
67  return -1;
68  offset += c->pos;
69  } else if (whence == SEEK_END) {
70  if (offset > INT64_MAX - c->filesize)
71  return -1;
72  offset += c->filesize;
73  } else if (whence == AVSEEK_SIZE) {
74  return c->filesize;
75  }
76  if (offset < 0 || offset > c->filesize)
77  return -1;
78  c->pos = offset;
79  return 0;
80 }
81 
82 // Ensure we don't loop forever
83 const uint32_t maxiteration = 8096;
84 
85 static const uint64_t FUZZ_TAG = 0x4741542D5A5A5546ULL;
86 
87 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
88  const uint64_t fuzz_tag = FUZZ_TAG;
89  uint32_t it = 0;
91  AVPacket pkt;
92  char filename[1025] = {0};
93  AVIOContext *fuzzed_pb = NULL;
94  uint8_t *io_buffer;
95  int io_buffer_size = 32768;
96  int64_t filesize = size;
97  IOContext opaque;
98  static int c;
99  int seekable = 0;
100  int ret;
101 
102  if (!c) {
103  av_register_all();
106  c=1;
107  }
108 
109  if (!avfmt)
110  error("Failed avformat_alloc_context()");
111 
112  if (size > 2048) {
113  GetByteContext gbc;
114  memcpy (filename, data + size - 1024, 1024);
115  bytestream2_init(&gbc, data + size - 2048, 1024);
116  size -= 2048;
117 
118  io_buffer_size = bytestream2_get_le32(&gbc) & 0xFFFFFFF;
119  seekable = bytestream2_get_byte(&gbc) & 1;
120  filesize = bytestream2_get_le64(&gbc) & 0x7FFFFFFFFFFFFFFF;
121  }
122  io_buffer = av_malloc(io_buffer_size);
123  if (!io_buffer)
124  error("Failed to allocate io_buffer");
125 
126  opaque.filesize = filesize;
127  opaque.pos = 0;
128  opaque.fuzz = data;
129  opaque.fuzz_size= size;
130  fuzzed_pb = avio_alloc_context(io_buffer, io_buffer_size, 0, &opaque,
131  io_read, NULL, seekable ? io_seek : NULL);
132  if (!fuzzed_pb)
133  error("avio_alloc_context failed");
134 
135  avfmt->pb = fuzzed_pb;
136 
137  ret = avformat_open_input(&avfmt, filename, NULL, NULL);
138  if (ret < 0) {
139  av_freep(&fuzzed_pb->buffer);
140  av_freep(&fuzzed_pb);
141  avformat_free_context(avfmt);
142  return 0;
143  }
144 
146 
148 
149  //TODO, test seeking
150 
151  for(it = 0; it < maxiteration; it++) {
152  ret = av_read_frame(avfmt, &pkt);
153  if (ret < 0)
154  break;
156  }
157 end:
158  av_freep(&fuzzed_pb->buffer);
159  av_freep(&fuzzed_pb);
160  avformat_close_input(&avfmt);
161 
162  return 0;
163 }
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:605
IOContext::filesize
int64_t filesize
Definition: target_dem_fuzzer.c:29
GetByteContext
Definition: bytestream.h:33
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:55
AV_LOG_PANIC
#define AV_LOG_PANIC
Something went really wrong and we will crash now.
Definition: log.h:163
IOContext::fuzz
uint8_t * fuzz
Definition: target_dem_fuzzer.c:30
end
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:92
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:531
data
const char data[16]
Definition: mxf.c:91
io_seek
static int64_t io_seek(void *opaque, int64_t offset, int whence)
Definition: target_dem_fuzzer.c:61
avcodec_register_all
void avcodec_register_all(void)
Register all the codecs, parsers and bitstream filters which were enabled at configuration time.
Definition: allcodecs.c:877
av_read_frame
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
Definition: utils.c:1780
IOContext::pos
int64_t pos
Definition: target_dem_fuzzer.c:28
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
avformat_close_input
void avformat_close_input(AVFormatContext **s)
Close an opened input AVFormatContext.
Definition: utils.c:4498
io_read
static int io_read(void *opaque, uint8_t *buf, int buf_size)
Definition: target_dem_fuzzer.c:42
avassert.h
IOContext::fuzz_size
int fuzz_size
Definition: target_dem_fuzzer.c:31
AVFormatContext
Format I/O context.
Definition: avformat.h:1335
NULL
#define NULL
Definition: coverity.c:32
FUZZ_TAG
static const uint64_t FUZZ_TAG
Definition: target_dem_fuzzer.c:85
AVFormatContext::pb
AVIOContext * pb
I/O context.
Definition: avformat.h:1377
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: utils.c:3622
AVIOContext
Bytestream IO Context.
Definition: avio.h:161
avformat_alloc_context
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition: options.c:144
FFMAX
#define FFMAX(a, b)
Definition: common.h:94
size
int size
Definition: twinvq_data.h:11134
FFMIN
#define FFMIN(a, b)
Definition: common.h:96
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_log_set_level
void av_log_set_level(int level)
Set the log level.
Definition: log.c:440
avformat_open_input
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:536
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:126
uint8_t
uint8_t
Definition: audio_convert.c:194
error
static void error(const char *err)
Definition: target_dem_fuzzer.c:36
avcodec.h
ret
ret
Definition: filter_design.txt:187
avformat.h
pkt
static AVPacket pkt
Definition: demuxing_decoding.c:54
avformat_free_context
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: utils.c:4455
LLVMFuzzerTestOneInput
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
Definition: target_dem_fuzzer.c:87
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:27
AVIOContext::buffer
unsigned char * buffer
Start of the buffer.
Definition: avio.h:226
AVPacket
This structure stores compressed data.
Definition: packet.h:332
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
bytestream.h
bytestream2_init
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:133
maxiteration
const uint32_t maxiteration
Definition: target_dem_fuzzer.c:83
av_init_packet
void av_init_packet(AVPacket *pkt)
Initialize optional fields of a packet with default values.
Definition: avpacket.c:35