FFmpeg
Loading...
Searching...
No Matches
target_enc_fuzzer.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2024 Michael Niedermayer <michael-ffmpeg@niedermayer.cc>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 * Based on target_dec_fuzzer
21 */
22
23#include "config.h"
24#include "libavutil/avassert.h"
25#include "libavutil/avstring.h"
26#include "libavutil/cpu.h"
27#include "libavutil/imgutils.h"
29#include "libavutil/mem.h"
30
31#include "libavcodec/avcodec.h"
35
36int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
37
38extern const FFCodec * codec_list[];
39
40static void error(const char *err)
41{
42 fprintf(stderr, "%s", err);
43 exit(1);
44}
45
46static const FFCodec *c = NULL;
47
48// Ensure we don't loop forever
49const uint32_t maxiteration = 8096;
50
51
53{
54 int ret;
55
56 ret = avcodec_send_frame(enc_ctx, frame);
57 if (ret < 0)
58 return ret;
59
60 while (ret >= 0) {
61 ret = avcodec_receive_packet(enc_ctx, pkt);
62 if (ret == AVERROR(EAGAIN)) {
63 return 0;
64 } else if (ret < 0) {
65 return ret;
66 }
67
69 }
70 av_assert0(0);
71}
72
73int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
74 uint64_t maxpixels_per_frame = 512 * 512;
75 uint64_t maxpixels;
76
77 const uint8_t *end = data + size;
78 uint32_t it = 0;
79 uint64_t nb_samples = 0;
81 uint64_t ec_pixels = 0;
82
83 if (!c) {
84#define ENCODER_SYMBOL0(CODEC) ff_##CODEC##_encoder
85#define ENCODER_SYMBOL(CODEC) ENCODER_SYMBOL0(CODEC)
86 extern FFCodec ENCODER_SYMBOL(FFMPEG_ENCODER);
87 codec_list[0] = &ENCODER_SYMBOL(FFMPEG_ENCODER);
88
89 c = &ENCODER_SYMBOL(FFMPEG_ENCODER);
91 }
92
93 if (c->p.type != AVMEDIA_TYPE_VIDEO)
94 return 0;
95
96 maxpixels = maxpixels_per_frame * maxiteration;
97 switch (c->p.id) {
98 case AV_CODEC_ID_A64_MULTI: maxpixels /= 65536; break;
99 case AV_CODEC_ID_A64_MULTI5: maxpixels /= 65536; break;
100 }
101
102 maxpixels_per_frame = FFMIN(maxpixels_per_frame , maxpixels);
103
105 if (!ctx)
106 error("Failed memory allocation");
107
108 if (ctx->max_pixels == 0 || ctx->max_pixels > maxpixels_per_frame)
109 ctx->max_pixels = maxpixels_per_frame; //To reduce false positive OOM and hangs
110
111 ctx->pix_fmt = AV_PIX_FMT_YUV420P;
112 if (size > 1024) {
113 GetByteContext gbc;
114 int flags;
115 av_unused int64_t flags64;
116
117 size -= 1024;
118 bytestream2_init(&gbc, data + size, 1024);
119 ctx->width = bytestream2_get_le32(&gbc) & 0xFFFF;
120 ctx->height = bytestream2_get_le32(&gbc) & 0xFFFF;
121 ctx->bit_rate = bytestream2_get_le64(&gbc);
122 ctx->gop_size = bytestream2_get_le32(&gbc) & 0x7FFFFFFF;
123 ctx->max_b_frames = bytestream2_get_le32(&gbc) & 0x7FFFFFFF;
124 ctx->time_base.num = bytestream2_get_le32(&gbc) & 0x7FFFFFFF;
125 ctx->time_base.den = bytestream2_get_le32(&gbc) & 0x7FFFFFFF;
126 ctx->framerate.num = bytestream2_get_le32(&gbc) & 0x7FFFFFFF;
127 ctx->framerate.den = bytestream2_get_le32(&gbc) & 0x7FFFFFFF;
128
129 flags = bytestream2_get_byte(&gbc);
130 if (flags & 2)
131 ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
132
133 if (flags & 0x40)
135
136 flags64 = bytestream2_get_le64(&gbc);
137
138 const enum AVPixelFormat *pix_fmts;
139 int pix_fmts_num;
141 0, (const void **) &pix_fmts,
142 &pix_fmts_num);
143 if (res >= 0 && pix_fmts_num > 0)
144 ctx->pix_fmt = pix_fmts[bytestream2_get_byte(&gbc) % pix_fmts_num];
145
146 switch (c->p.id) {
147 case AV_CODEC_ID_FFV1:{
148 int coder = bytestream2_get_byte(&gbc)&3;
149 if (coder == 3) coder = -2;
150 av_dict_set_int(&opts, "coder", coder, 0);
151 av_dict_set_int(&opts, "context", bytestream2_get_byte(&gbc)&1, 0);
152 av_dict_set_int(&opts, "slicecrc", bytestream2_get_byte(&gbc)&1, 0);
153 break;}
154 }
155 }
156 if (ctx->width == 0 || av_image_check_size(ctx->width, ctx->height, 0, ctx))
157 ctx->width = ctx->height = 64;
158
159 int res = avcodec_open2(ctx, &c->p, &opts);
160 if (res < 0) {
163 return 0; // Failure of avcodec_open2() does not imply that a issue was found
164 }
165
166
168 AVPacket *avpkt = av_packet_alloc();
169 if (!frame || !avpkt)
170 error("Failed memory allocation");
171
172 frame->format = ctx->pix_fmt;
173 frame->width = ctx->width;
174 frame->height = ctx->height;
175
176 while (data < end && it < maxiteration) {
177 ec_pixels += (ctx->width + 32LL) * (ctx->height + 32LL);
178 if (ec_pixels > maxpixels)
179 goto maximums_reached;
180
181 res = av_frame_get_buffer(frame, 0);
182 if (res < 0)
183 error("Failed av_frame_get_buffer");
184
185 for (int i=0; i<FF_ARRAY_ELEMS(frame->buf); i++) {
186 if (frame->buf[i]) {
187 int buf_size = FFMIN(end-data, frame->buf[i]->size);
188 memcpy(frame->buf[i]->data, data, buf_size);
189 memset(frame->buf[i]->data + buf_size, 0, frame->buf[i]->size - buf_size);
190 data += buf_size;
191 }
192 }
193
194 frame->pts = nb_samples;
195
196 res = encode(ctx, frame, avpkt);
197 if (res < 0)
198 break;
199 it++;
200 for (int i=0; i<FF_ARRAY_ELEMS(frame->buf); i++)
201 av_buffer_unref(&frame->buf[i]);
202
203 av_packet_unref(avpkt);
204 }
205maximums_reached:
206 encode(ctx, NULL, avpkt);
207 av_packet_unref(avpkt);
208
209// fprintf(stderr, "frames encoded: %"PRId64", iterations: %d\n", nb_samples , it);
210
213 av_packet_free(&avpkt);
215 return 0;
216}
static AVFormatContext * ctx
static AVDictionary * opts
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
Libavcodec external API header.
Main libavformat public API header.
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition bytestream.h:137
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
#define FF_COMPLIANCE_EXPERIMENTAL
Allow nonstandardized experimental things.
Definition defs.h:62
static AVPacket * pkt
static AVFrame * frame
int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
Initialize the AVCodecContext to use the given AVCodec.
Definition avcodec.c:144
AVCodecContext * avcodec_alloc_context3(const AVCodec *codec)
Allocate an AVCodecContext and set its fields to default values.
Definition options.c:149
void avcodec_free_context(AVCodecContext **avctx)
Free the codec context and everything associated with it and write NULL to the provided pointer.
Definition options.c:164
@ AV_CODEC_ID_FFV1
Definition codec_id.h:83
@ AV_CODEC_ID_A64_MULTI5
Definition codec_id.h:194
@ AV_CODEC_ID_A64_MULTI
Definition codec_id.h:193
int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
Read encoded data from the encoder.
Definition encode.c:578
int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame)
Supply a raw video or audio frame to the encoder.
Definition encode.c:545
int avcodec_get_supported_config(const AVCodecContext *avctx, const AVCodec *codec, enum AVCodecConfig config, unsigned flags, const void **out, int *out_num)
Retrieve a list of all supported values for a given configuration type.
Definition avcodec.c:818
@ AV_CODEC_CONFIG_PIX_FORMAT
AVPixelFormat, terminated by AV_PIX_FMT_NONE.
Definition avcodec.h:2573
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition packet.c:74
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition packet.c:434
AVPacket * av_packet_alloc(void)
Allocate an AVPacket and set its fields to default values.
Definition packet.c:63
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition buffer.c:139
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition dict.c:233
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
Convenience wrapper for av_dict_set() that converts the value to a string and stores it.
Definition dict.c:177
#define AVERROR(e)
Definition error.h:45
int av_frame_get_buffer(AVFrame *frame, int align)
Allocate new buffer(s) for audio or video data.
Definition frame.c:206
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition frame.c:52
#define AV_LOG_PANIC
Something went really wrong and we will crash now.
Definition log.h:197
void av_log_set_level(int level)
Set the log level.
Definition log.c:476
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
Check if the given dimension of an image is valid, meaning that all bytes of the image can be address...
Definition imgutils.c:318
misc image utilities
#define av_unused
Definition attributes.h:164
void av_force_cpu_flags(int arg)
Disables cpu detection and forces the specified flags.
Definition cpu.c:81
static enum AVPixelFormat pix_fmts[]
Definition libkvazaar.c:296
#define FFMIN(a, b)
Definition macros.h:49
Memory handling functions.
const char data[16]
Definition mxf.c:149
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
#define FF_ARRAY_ELEMS(a)
main external API structure.
Definition avcodec.h:443
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
This structure stores compressed data.
Definition packet.h:580
const uint32_t maxiteration
const FFCodec * codec_list[]
#define ENCODER_SYMBOL(CODEC)
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
static void error(const char *err)
static int encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt)
int size
static double c[64]