/src/ffmpeg/tools/target_bsf_fuzzer.c
Line | Count | Source |
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/imgutils.h" |
21 | | #include "libavutil/mem.h" |
22 | | #include "libavutil/opt.h" |
23 | | |
24 | | #include "libavcodec/avcodec.h" |
25 | | #include "libavcodec/bsf.h" |
26 | | #include "libavcodec/bsf_internal.h" |
27 | | #include "libavcodec/bytestream.h" |
28 | | #include "libavcodec/internal.h" |
29 | | |
30 | | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); |
31 | | |
32 | | static void error(const char *err) |
33 | 0 | { |
34 | 0 | fprintf(stderr, "%s", err); |
35 | 0 | exit(1); |
36 | 0 | } |
37 | | |
38 | | static const AVBitStreamFilter *f = NULL; |
39 | | |
40 | | static const uint64_t FUZZ_TAG = 0x4741542D5A5A5546ULL; |
41 | | |
42 | 80.7k | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
43 | 80.7k | const uint64_t fuzz_tag = FUZZ_TAG; |
44 | 80.7k | const uint8_t *last = data; |
45 | 80.7k | const uint8_t *end = data + size; |
46 | 80.7k | AVBSFContext *bsf = NULL; |
47 | 80.7k | AVPacket *pkt; |
48 | 80.7k | uint64_t keyframes = 0; |
49 | 80.7k | uint64_t flushpattern = -1; |
50 | 80.7k | int res; |
51 | | |
52 | 80.7k | if (!f) { |
53 | 55 | #ifdef FFMPEG_BSF |
54 | 55 | #define BSF_SYMBOL0(BSF) ff_##BSF##_bsf |
55 | 55 | #define BSF_SYMBOL(BSF) BSF_SYMBOL0(BSF) |
56 | 55 | extern const AVBitStreamFilter BSF_SYMBOL(FFMPEG_BSF); |
57 | 55 | f = &BSF_SYMBOL(FFMPEG_BSF); |
58 | 55 | #endif |
59 | 55 | av_log_set_level(AV_LOG_PANIC); |
60 | 55 | } |
61 | | |
62 | 80.7k | res = f ? av_bsf_alloc(f, &bsf) : av_bsf_get_null_filter(&bsf); |
63 | 80.7k | if (res == AVERROR(ENOTSUP)) |
64 | 2 | return 0; // multi-input filters cannot be used through av_bsf_alloc() |
65 | 80.7k | if (res < 0) |
66 | 0 | error("Failed memory allocation"); |
67 | 80.7k | f = bsf->filter; |
68 | | |
69 | 80.7k | if (size > 1024) { |
70 | 77.9k | GetByteContext gbc; |
71 | 77.9k | int extradata_size; |
72 | 77.9k | int flags; |
73 | 77.9k | size -= 1024; |
74 | 77.9k | bytestream2_init(&gbc, data + size, 1024); |
75 | 77.9k | bsf->par_in->width = bytestream2_get_le32(&gbc); |
76 | 77.9k | bsf->par_in->height = bytestream2_get_le32(&gbc); |
77 | 77.9k | bsf->par_in->bit_rate = bytestream2_get_le64(&gbc); |
78 | 77.9k | bsf->par_in->bits_per_coded_sample = bytestream2_get_le32(&gbc); |
79 | | |
80 | 77.9k | if (f->codec_ids) { |
81 | 75.5k | int i, id; |
82 | 296k | for (i = 0; f->codec_ids[i] != AV_CODEC_ID_NONE; i++); |
83 | 75.5k | id = f->codec_ids[bytestream2_get_byte(&gbc) % i]; |
84 | 75.5k | bsf->par_in->codec_id = id; |
85 | 75.5k | bsf->par_in->codec_tag = bytestream2_get_le32(&gbc); |
86 | 75.5k | } |
87 | | |
88 | 77.9k | extradata_size = bytestream2_get_le32(&gbc); |
89 | | |
90 | 77.9k | bsf->par_in->sample_rate = bytestream2_get_le32(&gbc); |
91 | 77.9k | bsf->par_in->ch_layout.nb_channels = (unsigned)bytestream2_get_le32(&gbc) % FF_SANE_NB_CHANNELS; |
92 | 77.9k | bsf->par_in->block_align = bytestream2_get_le32(&gbc); |
93 | 77.9k | keyframes = bytestream2_get_le64(&gbc); |
94 | 77.9k | flushpattern = bytestream2_get_le64(&gbc); |
95 | 77.9k | flags = bytestream2_get_byte(&gbc); |
96 | | |
97 | 77.9k | if (flags & 0x20) { |
98 | 29.0k | if (!strcmp(f->name, "av1_metadata")) |
99 | 1.10k | av_opt_set_int(bsf->priv_data, "td", bytestream2_get_byte(&gbc) % 3, 0); |
100 | 27.9k | else if (!strcmp(f->name, "h264_metadata") || !strcmp(f->name, "hevc_metadata") || |
101 | 24.1k | !strcmp(f->name, "vvc_metadata")) |
102 | 7.51k | av_opt_set_int(bsf->priv_data, "aud", bytestream2_get_byte(&gbc) % 3, 0); |
103 | 20.4k | else if (!strcmp(f->name, "extract_extradata")) |
104 | 617 | av_opt_set_int(bsf->priv_data, "remove", bytestream2_get_byte(&gbc) & 1, 0); |
105 | 29.0k | } |
106 | | |
107 | 77.9k | if (extradata_size < size) { |
108 | 11.9k | bsf->par_in->extradata = av_mallocz(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); |
109 | 11.9k | if (bsf->par_in->extradata) { |
110 | 11.9k | bsf->par_in->extradata_size = extradata_size; |
111 | 11.9k | size -= bsf->par_in->extradata_size; |
112 | 11.9k | memcpy(bsf->par_in->extradata, data + size, bsf->par_in->extradata_size); |
113 | 11.9k | } |
114 | 11.9k | } |
115 | 77.9k | if (av_image_check_size(bsf->par_in->width, bsf->par_in->height, 0, bsf)) |
116 | 75.1k | bsf->par_in->width = bsf->par_in->height = 0; |
117 | 77.9k | } |
118 | | |
119 | 80.7k | res = av_bsf_init(bsf); |
120 | 80.7k | if (res < 0) { |
121 | 2.94k | av_bsf_free(&bsf); |
122 | 2.94k | return 0; // Failure of av_bsf_init() does not imply that a issue was found |
123 | 2.94k | } |
124 | | |
125 | 77.7k | pkt = av_packet_alloc(); |
126 | 77.7k | if (!pkt) |
127 | 0 | error("Failed memory allocation"); |
128 | | |
129 | 20.6M | while (data < end) { |
130 | | // Search for the TAG |
131 | 3.37G | while (data + sizeof(fuzz_tag) < end) { |
132 | 3.37G | if (data[0] == (fuzz_tag & 0xFF) && AV_RN64(data) == fuzz_tag) |
133 | 20.4M | break; |
134 | 3.35G | data++; |
135 | 3.35G | } |
136 | 20.5M | if (data + sizeof(fuzz_tag) > end) |
137 | 5.36k | data = end; |
138 | | |
139 | 20.5M | res = av_new_packet(pkt, data - last); |
140 | 20.5M | if (res < 0) |
141 | 0 | error("Failed memory allocation"); |
142 | 20.5M | memcpy(pkt->data, last, data - last); |
143 | 20.5M | pkt->flags = (keyframes & 1) * AV_PKT_FLAG_DISCARD + (!!(keyframes & 2)) * AV_PKT_FLAG_KEY; |
144 | 20.5M | keyframes = (keyframes >> 2) + (keyframes<<62); |
145 | 20.5M | data += sizeof(fuzz_tag); |
146 | 20.5M | last = data; |
147 | | |
148 | 20.5M | if (!(flushpattern & 7)) |
149 | 5.51M | av_bsf_flush(bsf); |
150 | 20.5M | flushpattern = (flushpattern >> 3) + (flushpattern << 61); |
151 | | |
152 | 20.5M | res = av_bsf_send_packet(bsf, pkt); |
153 | 20.5M | if (res < 0) { |
154 | 612 | av_packet_unref(pkt); |
155 | 612 | continue; |
156 | 612 | } |
157 | 25.2M | while (av_bsf_receive_packet(bsf, pkt) >= 0) |
158 | 4.72M | av_packet_unref(pkt); |
159 | 20.5M | } |
160 | | |
161 | 77.7k | av_bsf_send_packet(bsf, NULL); |
162 | 96.0k | while (av_bsf_receive_packet(bsf, pkt) >= 0) |
163 | 18.2k | av_packet_unref(pkt); |
164 | | |
165 | 77.7k | av_packet_free(&pkt); |
166 | 77.7k | av_bsf_free(&bsf); |
167 | 77.7k | return 0; |
168 | 80.7k | } |