FFmpeg  4.3.9
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 {
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;
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 
145  ret = avformat_find_stream_info(avfmt, NULL);
146 
147  av_init_packet(&pkt);
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;
155  av_packet_unref(&pkt);
156  }
157 end:
158  av_freep(&fuzzed_pb->buffer);
159  av_freep(&fuzzed_pb);
160  avformat_close_input(&avfmt);
161 
162  return 0;
163 }
#define NULL
Definition: coverity.c:32
Bytestream IO Context.
Definition: avio.h:161
int size
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:133
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
static AVPacket pkt
static int io_read(void *opaque, uint8_t *buf, int buf_size)
Format I/O context.
Definition: avformat.h:1351
uint8_t
#define av_malloc(s)
#define AV_LOG_PANIC
Something went really wrong and we will crash now.
Definition: log.h:163
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:92
static const uint64_t FUZZ_TAG
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition: options.c:144
const char data[16]
Definition: mxf.c:91
#define AVERROR_EOF
End of file.
Definition: error.h:55
void avcodec_register_all(void)
Register all the codecs, parsers and bitstream filters which were enabled at configuration time...
Definition: allcodecs.c:877
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
simple assert() macros that are a bit more flexible than ISO C assert().
static const uint8_t offset[127][2]
Definition: vf_spp.c:93
#define FFMAX(a, b)
Definition: common.h:94
#define FFMIN(a, b)
Definition: common.h:96
int64_t filesize
uint8_t * fuzz
Libavcodec external API header.
AVIOContext * pb
I/O context.
Definition: avformat.h:1393
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:605
long long int64_t
Definition: coverity.c:34
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: utils.c:4455
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
Definition: utils.c:1780
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:3622
static double c[64]
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:4498
static void error(const char *err)
#define av_freep(p)
This structure stores compressed data.
Definition: packet.h:332
static int64_t io_seek(void *opaque, int64_t offset, int whence)