/src/ffmpeg/tools/target_dem_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/avassert.h" |
21 | | #include "libavutil/avstring.h" |
22 | | #include "libavutil/mem.h" |
23 | | |
24 | | #include "libavcodec/avcodec.h" |
25 | | #include "libavcodec/bytestream.h" |
26 | | #include "libavformat/avformat.h" |
27 | | #include "libavformat/demux.h" |
28 | | |
29 | | typedef struct IOContext { |
30 | | int64_t pos; |
31 | | int64_t filesize; |
32 | | const uint8_t *fuzz; |
33 | | int fuzz_size; |
34 | | } IOContext; |
35 | | |
36 | | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); |
37 | | |
38 | | int64_t interrupt_counter; |
39 | | static int interrupt_cb(void *ctx) |
40 | 123M | { |
41 | 123M | interrupt_counter --; |
42 | 123M | return interrupt_counter < 0; |
43 | 123M | } |
44 | | |
45 | | static void error(const char *err) |
46 | 0 | { |
47 | 0 | fprintf(stderr, "%s", err); |
48 | 0 | exit(1); |
49 | 0 | } |
50 | | |
51 | | static int io_read(void *opaque, uint8_t *buf, int buf_size) |
52 | 171M | { |
53 | 171M | IOContext *c = opaque; |
54 | 171M | int size = FFMIN(buf_size, c->fuzz_size); |
55 | | |
56 | 171M | if (!c->fuzz_size) { |
57 | 69.9M | c->filesize = FFMIN(c->pos, c->filesize); |
58 | 69.9M | return AVERROR_EOF; |
59 | 69.9M | } |
60 | 101M | if (c->pos > INT64_MAX - size) |
61 | 1.84k | return AVERROR(EIO); |
62 | | |
63 | 101M | memcpy(buf, c->fuzz, size); |
64 | 101M | c->fuzz += size; |
65 | 101M | c->fuzz_size -= size; |
66 | 101M | c->pos += size; |
67 | 101M | c->filesize = FFMAX(c->filesize, c->pos); |
68 | | |
69 | 101M | return size; |
70 | 101M | } |
71 | | |
72 | | static int64_t io_seek(void *opaque, int64_t offset, int whence) |
73 | 120M | { |
74 | 120M | IOContext *c = opaque; |
75 | | |
76 | 120M | if (whence == SEEK_CUR) { |
77 | 0 | if (offset > INT64_MAX - c->pos) |
78 | 0 | return -1; |
79 | 0 | offset += c->pos; |
80 | 120M | } else if (whence == SEEK_END) { |
81 | 0 | if (offset > INT64_MAX - c->filesize) |
82 | 0 | return -1; |
83 | 0 | offset += c->filesize; |
84 | 120M | } else if (whence == AVSEEK_SIZE) { |
85 | 51.4M | return c->filesize; |
86 | 51.4M | } |
87 | 69.4M | if (offset < 0 || offset > c->filesize) |
88 | 57.1M | return -1; |
89 | 12.2M | if (IO_FLAT) { |
90 | 58 | c->fuzz += offset - c->pos; |
91 | 58 | c->fuzz_size -= offset - c->pos; |
92 | 58 | } |
93 | 12.2M | c->pos = offset; |
94 | 12.2M | return 0; |
95 | 69.4M | } |
96 | | |
97 | | // Ensure we don't loop forever |
98 | | const uint32_t maxiteration = 8096; |
99 | | const int maxblocks= 50000; |
100 | | |
101 | 2.19M | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
102 | 2.19M | uint32_t it = 0; |
103 | 2.19M | AVFormatContext *avfmt = avformat_alloc_context(); |
104 | 2.19M | AVPacket *pkt; |
105 | 2.19M | char filename[1025] = {0}; |
106 | 2.19M | AVIOContext *fuzzed_pb = NULL; |
107 | 2.19M | uint8_t *io_buffer; |
108 | 2.19M | int io_buffer_size = 32768; |
109 | 2.19M | int64_t filesize = size; |
110 | 2.19M | IOContext opaque; |
111 | 2.19M | static int c; |
112 | 2.19M | int seekable = 0; |
113 | 2.19M | int ret; |
114 | 2.19M | const AVInputFormat *fmt = NULL; |
115 | | #ifdef FFMPEG_DEMUXER |
116 | 1.09M | #define DEMUXER_SYMBOL0(DEMUXER) ff_##DEMUXER##_demuxer |
117 | 1.09M | #define DEMUXER_SYMBOL(DEMUXER) DEMUXER_SYMBOL0(DEMUXER) |
118 | | extern const FFInputFormat DEMUXER_SYMBOL(FFMPEG_DEMUXER); |
119 | 1.09M | fmt = &DEMUXER_SYMBOL(FFMPEG_DEMUXER).p; |
120 | | #endif |
121 | | |
122 | 2.19M | if (!c) { |
123 | 716 | av_log_set_level(AV_LOG_PANIC); |
124 | 716 | c=1; |
125 | 716 | } |
126 | | |
127 | 2.19M | if (!avfmt) |
128 | 0 | error("Failed avformat_alloc_context()"); |
129 | | |
130 | 2.19M | if (IO_FLAT) { |
131 | 85.8k | seekable = 1; |
132 | 85.8k | io_buffer_size = size; |
133 | 2.11M | } else if (size > 2048) { |
134 | 773k | int flags; |
135 | 773k | char extension[64]; |
136 | | |
137 | 773k | GetByteContext gbc; |
138 | 773k | memcpy (filename, data + size - 1024, 1024); |
139 | 773k | bytestream2_init(&gbc, data + size - 2048, 1024); |
140 | 773k | size -= 2048; |
141 | | |
142 | 773k | io_buffer_size = bytestream2_get_le32(&gbc) & 0xFFFFFFF; |
143 | 773k | flags = bytestream2_get_byte(&gbc); |
144 | 773k | seekable = flags & 1; |
145 | 773k | filesize = bytestream2_get_le64(&gbc) & 0x7FFFFFFFFFFFFFFF; |
146 | | |
147 | 773k | if ((flags & 2) && strlen(filename) < sizeof(filename) / 2) { |
148 | 340k | const AVInputFormat *avif = NULL; |
149 | 340k | void *avif_iter = NULL; |
150 | 340k | int avif_count = 0; |
151 | 121M | while ((avif = av_demuxer_iterate(&avif_iter))) { |
152 | 121M | if (avif->extensions) |
153 | 58.5M | avif_count ++; |
154 | 121M | } |
155 | 340k | avif_count = bytestream2_get_le32(&gbc) % avif_count; |
156 | | |
157 | 340k | avif_iter = NULL; |
158 | 40.8M | while ((avif = av_demuxer_iterate(&avif_iter))) { |
159 | 40.8M | if (avif->extensions) |
160 | 22.0M | if (!avif_count--) |
161 | 340k | break; |
162 | 40.8M | } |
163 | 340k | av_strlcpy(extension, avif->extensions, sizeof(extension)); |
164 | 340k | if (strchr(extension, ',')) |
165 | 47.3k | *strchr(extension, ',') = 0; |
166 | 340k | av_strlcatf(filename, sizeof(filename), ".%s", extension); |
167 | 340k | } |
168 | | |
169 | 773k | interrupt_counter = bytestream2_get_le32(&gbc); |
170 | 773k | avfmt->interrupt_callback.callback = interrupt_cb; |
171 | 773k | } |
172 | | |
173 | | // HLS uses a loop with sleep, we thus must breakout or we timeout |
174 | 2.19M | if (fmt && !strcmp(fmt->name, "hls")) |
175 | 9.49k | interrupt_counter &= 31; |
176 | | |
177 | 2.19M | if (!io_buffer_size || size / io_buffer_size > maxblocks) |
178 | 59.9k | io_buffer_size = size; |
179 | | |
180 | 2.19M | pkt = av_packet_alloc(); |
181 | 2.19M | if (!pkt) |
182 | 0 | error("Failed to allocate pkt"); |
183 | | |
184 | 2.19M | io_buffer = av_malloc(io_buffer_size); |
185 | 2.19M | if (!io_buffer) |
186 | 0 | error("Failed to allocate io_buffer"); |
187 | | |
188 | 2.19M | opaque.filesize = filesize; |
189 | 2.19M | opaque.pos = 0; |
190 | 2.19M | opaque.fuzz = data; |
191 | 2.19M | opaque.fuzz_size= size; |
192 | 2.19M | fuzzed_pb = avio_alloc_context(io_buffer, io_buffer_size, 0, &opaque, |
193 | 2.19M | io_read, NULL, seekable ? io_seek : NULL); |
194 | 2.19M | if (!fuzzed_pb) |
195 | 0 | error("avio_alloc_context failed"); |
196 | | |
197 | 2.19M | avfmt->pb = fuzzed_pb; |
198 | | |
199 | 2.19M | ret = avformat_open_input(&avfmt, filename, fmt, NULL); |
200 | 2.19M | if (ret < 0) { |
201 | 506k | goto fail; |
202 | 506k | } |
203 | | |
204 | 1.69M | ret = avformat_find_stream_info(avfmt, NULL); |
205 | | |
206 | | //TODO, test seeking |
207 | | |
208 | 202M | for(it = 0; it < maxiteration; it++) { |
209 | 202M | ret = av_read_frame(avfmt, pkt); |
210 | 202M | if (ret < 0) |
211 | 1.67M | break; |
212 | 201M | av_packet_unref(pkt); |
213 | 201M | } |
214 | | |
215 | 2.19M | fail: |
216 | 2.19M | av_packet_free(&pkt); |
217 | 2.19M | av_freep(&fuzzed_pb->buffer); |
218 | 2.19M | avio_context_free(&fuzzed_pb); |
219 | 2.19M | avformat_close_input(&avfmt); |
220 | | |
221 | 2.19M | return 0; |
222 | | |
223 | 1.69M | } Line | Count | Source | 101 | 1.09M | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { | 102 | 1.09M | uint32_t it = 0; | 103 | 1.09M | AVFormatContext *avfmt = avformat_alloc_context(); | 104 | 1.09M | AVPacket *pkt; | 105 | 1.09M | char filename[1025] = {0}; | 106 | 1.09M | AVIOContext *fuzzed_pb = NULL; | 107 | 1.09M | uint8_t *io_buffer; | 108 | 1.09M | int io_buffer_size = 32768; | 109 | 1.09M | int64_t filesize = size; | 110 | 1.09M | IOContext opaque; | 111 | 1.09M | static int c; | 112 | 1.09M | int seekable = 0; | 113 | 1.09M | int ret; | 114 | 1.09M | const AVInputFormat *fmt = NULL; | 115 | 1.09M | #ifdef FFMPEG_DEMUXER | 116 | 1.09M | #define DEMUXER_SYMBOL0(DEMUXER) ff_##DEMUXER##_demuxer | 117 | 1.09M | #define DEMUXER_SYMBOL(DEMUXER) DEMUXER_SYMBOL0(DEMUXER) | 118 | 1.09M | extern const FFInputFormat DEMUXER_SYMBOL(FFMPEG_DEMUXER); | 119 | 1.09M | fmt = &DEMUXER_SYMBOL(FFMPEG_DEMUXER).p; | 120 | 1.09M | #endif | 121 | | | 122 | 1.09M | if (!c) { | 123 | 358 | av_log_set_level(AV_LOG_PANIC); | 124 | 358 | c=1; | 125 | 358 | } | 126 | | | 127 | 1.09M | if (!avfmt) | 128 | 0 | error("Failed avformat_alloc_context()"); | 129 | | | 130 | 1.09M | if (IO_FLAT) { | 131 | 42.9k | seekable = 1; | 132 | 42.9k | io_buffer_size = size; | 133 | 1.05M | } else if (size > 2048) { | 134 | 386k | int flags; | 135 | 386k | char extension[64]; | 136 | | | 137 | 386k | GetByteContext gbc; | 138 | 386k | memcpy (filename, data + size - 1024, 1024); | 139 | 386k | bytestream2_init(&gbc, data + size - 2048, 1024); | 140 | 386k | size -= 2048; | 141 | | | 142 | 386k | io_buffer_size = bytestream2_get_le32(&gbc) & 0xFFFFFFF; | 143 | 386k | flags = bytestream2_get_byte(&gbc); | 144 | 386k | seekable = flags & 1; | 145 | 386k | filesize = bytestream2_get_le64(&gbc) & 0x7FFFFFFFFFFFFFFF; | 146 | | | 147 | 386k | if ((flags & 2) && strlen(filename) < sizeof(filename) / 2) { | 148 | 170k | const AVInputFormat *avif = NULL; | 149 | 170k | void *avif_iter = NULL; | 150 | 170k | int avif_count = 0; | 151 | 60.7M | while ((avif = av_demuxer_iterate(&avif_iter))) { | 152 | 60.6M | if (avif->extensions) | 153 | 29.2M | avif_count ++; | 154 | 60.6M | } | 155 | 170k | avif_count = bytestream2_get_le32(&gbc) % avif_count; | 156 | | | 157 | 170k | avif_iter = NULL; | 158 | 20.4M | while ((avif = av_demuxer_iterate(&avif_iter))) { | 159 | 20.4M | if (avif->extensions) | 160 | 11.0M | if (!avif_count--) | 161 | 170k | break; | 162 | 20.4M | } | 163 | 170k | av_strlcpy(extension, avif->extensions, sizeof(extension)); | 164 | 170k | if (strchr(extension, ',')) | 165 | 23.6k | *strchr(extension, ',') = 0; | 166 | 170k | av_strlcatf(filename, sizeof(filename), ".%s", extension); | 167 | 170k | } | 168 | | | 169 | 386k | interrupt_counter = bytestream2_get_le32(&gbc); | 170 | 386k | avfmt->interrupt_callback.callback = interrupt_cb; | 171 | 386k | } | 172 | | | 173 | | // HLS uses a loop with sleep, we thus must breakout or we timeout | 174 | 1.09M | if (fmt && !strcmp(fmt->name, "hls")) | 175 | 4.74k | interrupt_counter &= 31; | 176 | | | 177 | 1.09M | if (!io_buffer_size || size / io_buffer_size > maxblocks) | 178 | 29.9k | io_buffer_size = size; | 179 | | | 180 | 1.09M | pkt = av_packet_alloc(); | 181 | 1.09M | if (!pkt) | 182 | 0 | error("Failed to allocate pkt"); | 183 | | | 184 | 1.09M | io_buffer = av_malloc(io_buffer_size); | 185 | 1.09M | if (!io_buffer) | 186 | 0 | error("Failed to allocate io_buffer"); | 187 | | | 188 | 1.09M | opaque.filesize = filesize; | 189 | 1.09M | opaque.pos = 0; | 190 | 1.09M | opaque.fuzz = data; | 191 | 1.09M | opaque.fuzz_size= size; | 192 | 1.09M | fuzzed_pb = avio_alloc_context(io_buffer, io_buffer_size, 0, &opaque, | 193 | 1.09M | io_read, NULL, seekable ? io_seek : NULL); | 194 | 1.09M | if (!fuzzed_pb) | 195 | 0 | error("avio_alloc_context failed"); | 196 | | | 197 | 1.09M | avfmt->pb = fuzzed_pb; | 198 | | | 199 | 1.09M | ret = avformat_open_input(&avfmt, filename, fmt, NULL); | 200 | 1.09M | if (ret < 0) { | 201 | 253k | goto fail; | 202 | 253k | } | 203 | | | 204 | 845k | ret = avformat_find_stream_info(avfmt, NULL); | 205 | | | 206 | | //TODO, test seeking | 207 | | | 208 | 101M | for(it = 0; it < maxiteration; it++) { | 209 | 101M | ret = av_read_frame(avfmt, pkt); | 210 | 101M | if (ret < 0) | 211 | 838k | break; | 212 | 100M | av_packet_unref(pkt); | 213 | 100M | } | 214 | | | 215 | 1.09M | fail: | 216 | 1.09M | av_packet_free(&pkt); | 217 | 1.09M | av_freep(&fuzzed_pb->buffer); | 218 | 1.09M | avio_context_free(&fuzzed_pb); | 219 | 1.09M | avformat_close_input(&avfmt); | 220 | | | 221 | 1.09M | return 0; | 222 | | | 223 | 845k | } |
Line | Count | Source | 101 | 1.09M | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { | 102 | 1.09M | uint32_t it = 0; | 103 | 1.09M | AVFormatContext *avfmt = avformat_alloc_context(); | 104 | 1.09M | AVPacket *pkt; | 105 | 1.09M | char filename[1025] = {0}; | 106 | 1.09M | AVIOContext *fuzzed_pb = NULL; | 107 | 1.09M | uint8_t *io_buffer; | 108 | 1.09M | int io_buffer_size = 32768; | 109 | 1.09M | int64_t filesize = size; | 110 | 1.09M | IOContext opaque; | 111 | 1.09M | static int c; | 112 | 1.09M | int seekable = 0; | 113 | 1.09M | int ret; | 114 | 1.09M | const AVInputFormat *fmt = NULL; | 115 | | #ifdef FFMPEG_DEMUXER | 116 | | #define DEMUXER_SYMBOL0(DEMUXER) ff_##DEMUXER##_demuxer | 117 | | #define DEMUXER_SYMBOL(DEMUXER) DEMUXER_SYMBOL0(DEMUXER) | 118 | | extern const FFInputFormat DEMUXER_SYMBOL(FFMPEG_DEMUXER); | 119 | | fmt = &DEMUXER_SYMBOL(FFMPEG_DEMUXER).p; | 120 | | #endif | 121 | | | 122 | 1.09M | if (!c) { | 123 | 358 | av_log_set_level(AV_LOG_PANIC); | 124 | 358 | c=1; | 125 | 358 | } | 126 | | | 127 | 1.09M | if (!avfmt) | 128 | 0 | error("Failed avformat_alloc_context()"); | 129 | | | 130 | 1.09M | if (IO_FLAT) { | 131 | 42.9k | seekable = 1; | 132 | 42.9k | io_buffer_size = size; | 133 | 1.05M | } else if (size > 2048) { | 134 | 386k | int flags; | 135 | 386k | char extension[64]; | 136 | | | 137 | 386k | GetByteContext gbc; | 138 | 386k | memcpy (filename, data + size - 1024, 1024); | 139 | 386k | bytestream2_init(&gbc, data + size - 2048, 1024); | 140 | 386k | size -= 2048; | 141 | | | 142 | 386k | io_buffer_size = bytestream2_get_le32(&gbc) & 0xFFFFFFF; | 143 | 386k | flags = bytestream2_get_byte(&gbc); | 144 | 386k | seekable = flags & 1; | 145 | 386k | filesize = bytestream2_get_le64(&gbc) & 0x7FFFFFFFFFFFFFFF; | 146 | | | 147 | 386k | if ((flags & 2) && strlen(filename) < sizeof(filename) / 2) { | 148 | 170k | const AVInputFormat *avif = NULL; | 149 | 170k | void *avif_iter = NULL; | 150 | 170k | int avif_count = 0; | 151 | 60.7M | while ((avif = av_demuxer_iterate(&avif_iter))) { | 152 | 60.6M | if (avif->extensions) | 153 | 29.2M | avif_count ++; | 154 | 60.6M | } | 155 | 170k | avif_count = bytestream2_get_le32(&gbc) % avif_count; | 156 | | | 157 | 170k | avif_iter = NULL; | 158 | 20.4M | while ((avif = av_demuxer_iterate(&avif_iter))) { | 159 | 20.4M | if (avif->extensions) | 160 | 11.0M | if (!avif_count--) | 161 | 170k | break; | 162 | 20.4M | } | 163 | 170k | av_strlcpy(extension, avif->extensions, sizeof(extension)); | 164 | 170k | if (strchr(extension, ',')) | 165 | 23.6k | *strchr(extension, ',') = 0; | 166 | 170k | av_strlcatf(filename, sizeof(filename), ".%s", extension); | 167 | 170k | } | 168 | | | 169 | 386k | interrupt_counter = bytestream2_get_le32(&gbc); | 170 | 386k | avfmt->interrupt_callback.callback = interrupt_cb; | 171 | 386k | } | 172 | | | 173 | | // HLS uses a loop with sleep, we thus must breakout or we timeout | 174 | 1.09M | if (fmt && !strcmp(fmt->name, "hls")) | 175 | 4.74k | interrupt_counter &= 31; | 176 | | | 177 | 1.09M | if (!io_buffer_size || size / io_buffer_size > maxblocks) | 178 | 29.9k | io_buffer_size = size; | 179 | | | 180 | 1.09M | pkt = av_packet_alloc(); | 181 | 1.09M | if (!pkt) | 182 | 0 | error("Failed to allocate pkt"); | 183 | | | 184 | 1.09M | io_buffer = av_malloc(io_buffer_size); | 185 | 1.09M | if (!io_buffer) | 186 | 0 | error("Failed to allocate io_buffer"); | 187 | | | 188 | 1.09M | opaque.filesize = filesize; | 189 | 1.09M | opaque.pos = 0; | 190 | 1.09M | opaque.fuzz = data; | 191 | 1.09M | opaque.fuzz_size= size; | 192 | 1.09M | fuzzed_pb = avio_alloc_context(io_buffer, io_buffer_size, 0, &opaque, | 193 | 1.09M | io_read, NULL, seekable ? io_seek : NULL); | 194 | 1.09M | if (!fuzzed_pb) | 195 | 0 | error("avio_alloc_context failed"); | 196 | | | 197 | 1.09M | avfmt->pb = fuzzed_pb; | 198 | | | 199 | 1.09M | ret = avformat_open_input(&avfmt, filename, fmt, NULL); | 200 | 1.09M | if (ret < 0) { | 201 | 253k | goto fail; | 202 | 253k | } | 203 | | | 204 | 845k | ret = avformat_find_stream_info(avfmt, NULL); | 205 | | | 206 | | //TODO, test seeking | 207 | | | 208 | 101M | for(it = 0; it < maxiteration; it++) { | 209 | 101M | ret = av_read_frame(avfmt, pkt); | 210 | 101M | if (ret < 0) | 211 | 838k | break; | 212 | 100M | av_packet_unref(pkt); | 213 | 100M | } | 214 | | | 215 | 1.09M | fail: | 216 | 1.09M | av_packet_free(&pkt); | 217 | 1.09M | av_freep(&fuzzed_pb->buffer); | 218 | 1.09M | avio_context_free(&fuzzed_pb); | 219 | 1.09M | avformat_close_input(&avfmt); | 220 | | | 221 | 1.09M | return 0; | 222 | | | 223 | 845k | } |
|