/src/ffmpeg/tools/target_dem_fuzzer.c
Line | Count | Source (jump to first uncovered line) |
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 | 104M | { |
41 | 104M | interrupt_counter --; |
42 | 104M | return interrupt_counter < 0; |
43 | 104M | } |
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 | 481M | { |
53 | 481M | IOContext *c = opaque; |
54 | 481M | int size = FFMIN(buf_size, c->fuzz_size); |
55 | | |
56 | 481M | if (!c->fuzz_size) { |
57 | 50.5M | c->filesize = FFMIN(c->pos, c->filesize); |
58 | 50.5M | return AVERROR_EOF; |
59 | 50.5M | } |
60 | 431M | if (c->pos > INT64_MAX - size) |
61 | 2.17k | return AVERROR(EIO); |
62 | | |
63 | 431M | memcpy(buf, c->fuzz, size); |
64 | 431M | c->fuzz += size; |
65 | 431M | c->fuzz_size -= size; |
66 | 431M | c->pos += size; |
67 | 431M | c->filesize = FFMAX(c->filesize, c->pos); |
68 | | |
69 | 431M | return size; |
70 | 431M | } |
71 | | |
72 | | static int64_t io_seek(void *opaque, int64_t offset, int whence) |
73 | 338M | { |
74 | 338M | IOContext *c = opaque; |
75 | | |
76 | 338M | if (whence == SEEK_CUR) { |
77 | 0 | if (offset > INT64_MAX - c->pos) |
78 | 0 | return -1; |
79 | 0 | offset += c->pos; |
80 | 338M | } else if (whence == SEEK_END) { |
81 | 0 | if (offset > INT64_MAX - c->filesize) |
82 | 0 | return -1; |
83 | 0 | offset += c->filesize; |
84 | 338M | } else if (whence == AVSEEK_SIZE) { |
85 | 43.7M | return c->filesize; |
86 | 43.7M | } |
87 | 294M | if (offset < 0 || offset > c->filesize) |
88 | 9.59M | return -1; |
89 | 284M | if (IO_FLAT) { |
90 | 37 | c->fuzz += offset - c->pos; |
91 | 37 | c->fuzz_size -= offset - c->pos; |
92 | 37 | } |
93 | 284M | c->pos = offset; |
94 | 284M | return 0; |
95 | 294M | } |
96 | | |
97 | | // Ensure we don't loop forever |
98 | | const uint32_t maxiteration = 8096; |
99 | | const int maxblocks= 50000; |
100 | | |
101 | 5.15M | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
102 | 5.15M | uint32_t it = 0; |
103 | 5.15M | AVFormatContext *avfmt = avformat_alloc_context(); |
104 | 5.15M | AVPacket *pkt; |
105 | 5.15M | char filename[1025] = {0}; |
106 | 5.15M | AVIOContext *fuzzed_pb = NULL; |
107 | 5.15M | uint8_t *io_buffer; |
108 | 5.15M | int io_buffer_size = 32768; |
109 | 5.15M | int64_t filesize = size; |
110 | 5.15M | IOContext opaque; |
111 | 5.15M | static int c; |
112 | 5.15M | int seekable = 0; |
113 | 5.15M | int ret; |
114 | 5.15M | const AVInputFormat *fmt = NULL; |
115 | | #ifdef FFMPEG_DEMUXER |
116 | 2.57M | #define DEMUXER_SYMBOL0(DEMUXER) ff_##DEMUXER##_demuxer |
117 | 2.57M | #define DEMUXER_SYMBOL(DEMUXER) DEMUXER_SYMBOL0(DEMUXER) |
118 | | extern const FFInputFormat DEMUXER_SYMBOL(FFMPEG_DEMUXER); |
119 | 2.57M | fmt = &DEMUXER_SYMBOL(FFMPEG_DEMUXER).p; |
120 | | #endif |
121 | | |
122 | 5.15M | if (!c) { |
123 | 712 | av_log_set_level(AV_LOG_PANIC); |
124 | 712 | c=1; |
125 | 712 | } |
126 | | |
127 | 5.15M | if (!avfmt) |
128 | 0 | error("Failed avformat_alloc_context()"); |
129 | | |
130 | 5.15M | if (IO_FLAT) { |
131 | 76.9k | seekable = 1; |
132 | 76.9k | io_buffer_size = size; |
133 | 5.08M | } else if (size > 2048) { |
134 | 1.12M | int flags; |
135 | 1.12M | char extension[64]; |
136 | | |
137 | 1.12M | GetByteContext gbc; |
138 | 1.12M | memcpy (filename, data + size - 1024, 1024); |
139 | 1.12M | bytestream2_init(&gbc, data + size - 2048, 1024); |
140 | 1.12M | size -= 2048; |
141 | | |
142 | 1.12M | io_buffer_size = bytestream2_get_le32(&gbc) & 0xFFFFFFF; |
143 | 1.12M | flags = bytestream2_get_byte(&gbc); |
144 | 1.12M | seekable = flags & 1; |
145 | 1.12M | filesize = bytestream2_get_le64(&gbc) & 0x7FFFFFFFFFFFFFFF; |
146 | | |
147 | 1.12M | if ((flags & 2) && strlen(filename) < sizeof(filename) / 2) { |
148 | 422k | const AVInputFormat *avif = NULL; |
149 | 422k | void *avif_iter = NULL; |
150 | 422k | int avif_count = 0; |
151 | 149M | while ((avif = av_demuxer_iterate(&avif_iter))) { |
152 | 149M | if (avif->extensions) |
153 | 72.1M | avif_count ++; |
154 | 149M | } |
155 | 422k | avif_count = bytestream2_get_le32(&gbc) % avif_count; |
156 | | |
157 | 422k | avif_iter = NULL; |
158 | 63.2M | while ((avif = av_demuxer_iterate(&avif_iter))) { |
159 | 63.2M | if (avif->extensions) |
160 | 33.7M | if (!avif_count--) |
161 | 422k | break; |
162 | 63.2M | } |
163 | 422k | av_strlcpy(extension, avif->extensions, sizeof(extension)); |
164 | 422k | if (strchr(extension, ',')) |
165 | 60.0k | *strchr(extension, ',') = 0; |
166 | 422k | av_strlcatf(filename, sizeof(filename), ".%s", extension); |
167 | 422k | } |
168 | | |
169 | 1.12M | interrupt_counter = bytestream2_get_le32(&gbc); |
170 | 1.12M | avfmt->interrupt_callback.callback = interrupt_cb; |
171 | 1.12M | } |
172 | | |
173 | | // HLS uses a loop with sleep, we thus must breakout or we timeout |
174 | 5.15M | if (fmt && !strcmp(fmt->name, "hls")) |
175 | 17.5k | interrupt_counter &= 31; |
176 | | |
177 | 5.15M | if (!io_buffer_size || size / io_buffer_size > maxblocks) |
178 | 61.9k | io_buffer_size = size; |
179 | | |
180 | 5.15M | pkt = av_packet_alloc(); |
181 | 5.15M | if (!pkt) |
182 | 0 | error("Failed to allocate pkt"); |
183 | | |
184 | 5.15M | io_buffer = av_malloc(io_buffer_size); |
185 | 5.15M | if (!io_buffer) |
186 | 0 | error("Failed to allocate io_buffer"); |
187 | | |
188 | 5.15M | opaque.filesize = filesize; |
189 | 5.15M | opaque.pos = 0; |
190 | 5.15M | opaque.fuzz = data; |
191 | 5.15M | opaque.fuzz_size= size; |
192 | 5.15M | fuzzed_pb = avio_alloc_context(io_buffer, io_buffer_size, 0, &opaque, |
193 | 5.15M | io_read, NULL, seekable ? io_seek : NULL); |
194 | 5.15M | if (!fuzzed_pb) |
195 | 0 | error("avio_alloc_context failed"); |
196 | | |
197 | 5.15M | avfmt->pb = fuzzed_pb; |
198 | | |
199 | 5.15M | ret = avformat_open_input(&avfmt, filename, fmt, NULL); |
200 | 5.15M | if (ret < 0) { |
201 | 2.11M | goto fail; |
202 | 2.11M | } |
203 | | |
204 | 3.04M | ret = avformat_find_stream_info(avfmt, NULL); |
205 | | |
206 | | //TODO, test seeking |
207 | | |
208 | 156M | for(it = 0; it < maxiteration; it++) { |
209 | 156M | ret = av_read_frame(avfmt, pkt); |
210 | 156M | if (ret < 0) |
211 | 3.03M | break; |
212 | 153M | av_packet_unref(pkt); |
213 | 153M | } |
214 | | |
215 | 5.15M | fail: |
216 | 5.15M | av_packet_free(&pkt); |
217 | 5.15M | av_freep(&fuzzed_pb->buffer); |
218 | 5.15M | avio_context_free(&fuzzed_pb); |
219 | 5.15M | avformat_close_input(&avfmt); |
220 | | |
221 | 5.15M | return 0; |
222 | | |
223 | 3.04M | } Line | Count | Source | 101 | 2.57M | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { | 102 | 2.57M | uint32_t it = 0; | 103 | 2.57M | AVFormatContext *avfmt = avformat_alloc_context(); | 104 | 2.57M | AVPacket *pkt; | 105 | 2.57M | char filename[1025] = {0}; | 106 | 2.57M | AVIOContext *fuzzed_pb = NULL; | 107 | 2.57M | uint8_t *io_buffer; | 108 | 2.57M | int io_buffer_size = 32768; | 109 | 2.57M | int64_t filesize = size; | 110 | 2.57M | IOContext opaque; | 111 | 2.57M | static int c; | 112 | 2.57M | int seekable = 0; | 113 | 2.57M | int ret; | 114 | 2.57M | const AVInputFormat *fmt = NULL; | 115 | 2.57M | #ifdef FFMPEG_DEMUXER | 116 | 2.57M | #define DEMUXER_SYMBOL0(DEMUXER) ff_##DEMUXER##_demuxer | 117 | 2.57M | #define DEMUXER_SYMBOL(DEMUXER) DEMUXER_SYMBOL0(DEMUXER) | 118 | 2.57M | extern const FFInputFormat DEMUXER_SYMBOL(FFMPEG_DEMUXER); | 119 | 2.57M | fmt = &DEMUXER_SYMBOL(FFMPEG_DEMUXER).p; | 120 | 2.57M | #endif | 121 | | | 122 | 2.57M | if (!c) { | 123 | 356 | av_log_set_level(AV_LOG_PANIC); | 124 | 356 | c=1; | 125 | 356 | } | 126 | | | 127 | 2.57M | if (!avfmt) | 128 | 0 | error("Failed avformat_alloc_context()"); | 129 | | | 130 | 2.57M | if (IO_FLAT) { | 131 | 38.4k | seekable = 1; | 132 | 38.4k | io_buffer_size = size; | 133 | 2.54M | } else if (size > 2048) { | 134 | 562k | int flags; | 135 | 562k | char extension[64]; | 136 | | | 137 | 562k | GetByteContext gbc; | 138 | 562k | memcpy (filename, data + size - 1024, 1024); | 139 | 562k | bytestream2_init(&gbc, data + size - 2048, 1024); | 140 | 562k | size -= 2048; | 141 | | | 142 | 562k | io_buffer_size = bytestream2_get_le32(&gbc) & 0xFFFFFFF; | 143 | 562k | flags = bytestream2_get_byte(&gbc); | 144 | 562k | seekable = flags & 1; | 145 | 562k | filesize = bytestream2_get_le64(&gbc) & 0x7FFFFFFFFFFFFFFF; | 146 | | | 147 | 562k | if ((flags & 2) && strlen(filename) < sizeof(filename) / 2) { | 148 | 211k | const AVInputFormat *avif = NULL; | 149 | 211k | void *avif_iter = NULL; | 150 | 211k | int avif_count = 0; | 151 | 74.9M | while ((avif = av_demuxer_iterate(&avif_iter))) { | 152 | 74.7M | if (avif->extensions) | 153 | 36.0M | avif_count ++; | 154 | 74.7M | } | 155 | 211k | avif_count = bytestream2_get_le32(&gbc) % avif_count; | 156 | | | 157 | 211k | avif_iter = NULL; | 158 | 31.6M | while ((avif = av_demuxer_iterate(&avif_iter))) { | 159 | 31.6M | if (avif->extensions) | 160 | 16.8M | if (!avif_count--) | 161 | 211k | break; | 162 | 31.6M | } | 163 | 211k | av_strlcpy(extension, avif->extensions, sizeof(extension)); | 164 | 211k | if (strchr(extension, ',')) | 165 | 30.0k | *strchr(extension, ',') = 0; | 166 | 211k | av_strlcatf(filename, sizeof(filename), ".%s", extension); | 167 | 211k | } | 168 | | | 169 | 562k | interrupt_counter = bytestream2_get_le32(&gbc); | 170 | 562k | avfmt->interrupt_callback.callback = interrupt_cb; | 171 | 562k | } | 172 | | | 173 | | // HLS uses a loop with sleep, we thus must breakout or we timeout | 174 | 2.57M | if (fmt && !strcmp(fmt->name, "hls")) | 175 | 8.76k | interrupt_counter &= 31; | 176 | | | 177 | 2.57M | if (!io_buffer_size || size / io_buffer_size > maxblocks) | 178 | 30.9k | io_buffer_size = size; | 179 | | | 180 | 2.57M | pkt = av_packet_alloc(); | 181 | 2.57M | if (!pkt) | 182 | 0 | error("Failed to allocate pkt"); | 183 | | | 184 | 2.57M | io_buffer = av_malloc(io_buffer_size); | 185 | 2.57M | if (!io_buffer) | 186 | 0 | error("Failed to allocate io_buffer"); | 187 | | | 188 | 2.57M | opaque.filesize = filesize; | 189 | 2.57M | opaque.pos = 0; | 190 | 2.57M | opaque.fuzz = data; | 191 | 2.57M | opaque.fuzz_size= size; | 192 | 2.57M | fuzzed_pb = avio_alloc_context(io_buffer, io_buffer_size, 0, &opaque, | 193 | 2.57M | io_read, NULL, seekable ? io_seek : NULL); | 194 | 2.57M | if (!fuzzed_pb) | 195 | 0 | error("avio_alloc_context failed"); | 196 | | | 197 | 2.57M | avfmt->pb = fuzzed_pb; | 198 | | | 199 | 2.57M | ret = avformat_open_input(&avfmt, filename, fmt, NULL); | 200 | 2.57M | if (ret < 0) { | 201 | 1.05M | goto fail; | 202 | 1.05M | } | 203 | | | 204 | 1.52M | ret = avformat_find_stream_info(avfmt, NULL); | 205 | | | 206 | | //TODO, test seeking | 207 | | | 208 | 78.1M | for(it = 0; it < maxiteration; it++) { | 209 | 78.1M | ret = av_read_frame(avfmt, pkt); | 210 | 78.1M | if (ret < 0) | 211 | 1.51M | break; | 212 | 76.6M | av_packet_unref(pkt); | 213 | 76.6M | } | 214 | | | 215 | 2.57M | fail: | 216 | 2.57M | av_packet_free(&pkt); | 217 | 2.57M | av_freep(&fuzzed_pb->buffer); | 218 | 2.57M | avio_context_free(&fuzzed_pb); | 219 | 2.57M | avformat_close_input(&avfmt); | 220 | | | 221 | 2.57M | return 0; | 222 | | | 223 | 1.52M | } |
Line | Count | Source | 101 | 2.57M | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { | 102 | 2.57M | uint32_t it = 0; | 103 | 2.57M | AVFormatContext *avfmt = avformat_alloc_context(); | 104 | 2.57M | AVPacket *pkt; | 105 | 2.57M | char filename[1025] = {0}; | 106 | 2.57M | AVIOContext *fuzzed_pb = NULL; | 107 | 2.57M | uint8_t *io_buffer; | 108 | 2.57M | int io_buffer_size = 32768; | 109 | 2.57M | int64_t filesize = size; | 110 | 2.57M | IOContext opaque; | 111 | 2.57M | static int c; | 112 | 2.57M | int seekable = 0; | 113 | 2.57M | int ret; | 114 | 2.57M | 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 | 2.57M | if (!c) { | 123 | 356 | av_log_set_level(AV_LOG_PANIC); | 124 | 356 | c=1; | 125 | 356 | } | 126 | | | 127 | 2.57M | if (!avfmt) | 128 | 0 | error("Failed avformat_alloc_context()"); | 129 | | | 130 | 2.57M | if (IO_FLAT) { | 131 | 38.4k | seekable = 1; | 132 | 38.4k | io_buffer_size = size; | 133 | 2.54M | } else if (size > 2048) { | 134 | 562k | int flags; | 135 | 562k | char extension[64]; | 136 | | | 137 | 562k | GetByteContext gbc; | 138 | 562k | memcpy (filename, data + size - 1024, 1024); | 139 | 562k | bytestream2_init(&gbc, data + size - 2048, 1024); | 140 | 562k | size -= 2048; | 141 | | | 142 | 562k | io_buffer_size = bytestream2_get_le32(&gbc) & 0xFFFFFFF; | 143 | 562k | flags = bytestream2_get_byte(&gbc); | 144 | 562k | seekable = flags & 1; | 145 | 562k | filesize = bytestream2_get_le64(&gbc) & 0x7FFFFFFFFFFFFFFF; | 146 | | | 147 | 562k | if ((flags & 2) && strlen(filename) < sizeof(filename) / 2) { | 148 | 211k | const AVInputFormat *avif = NULL; | 149 | 211k | void *avif_iter = NULL; | 150 | 211k | int avif_count = 0; | 151 | 74.9M | while ((avif = av_demuxer_iterate(&avif_iter))) { | 152 | 74.7M | if (avif->extensions) | 153 | 36.0M | avif_count ++; | 154 | 74.7M | } | 155 | 211k | avif_count = bytestream2_get_le32(&gbc) % avif_count; | 156 | | | 157 | 211k | avif_iter = NULL; | 158 | 31.6M | while ((avif = av_demuxer_iterate(&avif_iter))) { | 159 | 31.6M | if (avif->extensions) | 160 | 16.8M | if (!avif_count--) | 161 | 211k | break; | 162 | 31.6M | } | 163 | 211k | av_strlcpy(extension, avif->extensions, sizeof(extension)); | 164 | 211k | if (strchr(extension, ',')) | 165 | 30.0k | *strchr(extension, ',') = 0; | 166 | 211k | av_strlcatf(filename, sizeof(filename), ".%s", extension); | 167 | 211k | } | 168 | | | 169 | 562k | interrupt_counter = bytestream2_get_le32(&gbc); | 170 | 562k | avfmt->interrupt_callback.callback = interrupt_cb; | 171 | 562k | } | 172 | | | 173 | | // HLS uses a loop with sleep, we thus must breakout or we timeout | 174 | 2.57M | if (fmt && !strcmp(fmt->name, "hls")) | 175 | 8.76k | interrupt_counter &= 31; | 176 | | | 177 | 2.57M | if (!io_buffer_size || size / io_buffer_size > maxblocks) | 178 | 30.9k | io_buffer_size = size; | 179 | | | 180 | 2.57M | pkt = av_packet_alloc(); | 181 | 2.57M | if (!pkt) | 182 | 0 | error("Failed to allocate pkt"); | 183 | | | 184 | 2.57M | io_buffer = av_malloc(io_buffer_size); | 185 | 2.57M | if (!io_buffer) | 186 | 0 | error("Failed to allocate io_buffer"); | 187 | | | 188 | 2.57M | opaque.filesize = filesize; | 189 | 2.57M | opaque.pos = 0; | 190 | 2.57M | opaque.fuzz = data; | 191 | 2.57M | opaque.fuzz_size= size; | 192 | 2.57M | fuzzed_pb = avio_alloc_context(io_buffer, io_buffer_size, 0, &opaque, | 193 | 2.57M | io_read, NULL, seekable ? io_seek : NULL); | 194 | 2.57M | if (!fuzzed_pb) | 195 | 0 | error("avio_alloc_context failed"); | 196 | | | 197 | 2.57M | avfmt->pb = fuzzed_pb; | 198 | | | 199 | 2.57M | ret = avformat_open_input(&avfmt, filename, fmt, NULL); | 200 | 2.57M | if (ret < 0) { | 201 | 1.05M | goto fail; | 202 | 1.05M | } | 203 | | | 204 | 1.52M | ret = avformat_find_stream_info(avfmt, NULL); | 205 | | | 206 | | //TODO, test seeking | 207 | | | 208 | 78.1M | for(it = 0; it < maxiteration; it++) { | 209 | 78.1M | ret = av_read_frame(avfmt, pkt); | 210 | 78.1M | if (ret < 0) | 211 | 1.51M | break; | 212 | 76.6M | av_packet_unref(pkt); | 213 | 76.6M | } | 214 | | | 215 | 2.57M | fail: | 216 | 2.57M | av_packet_free(&pkt); | 217 | 2.57M | av_freep(&fuzzed_pb->buffer); | 218 | 2.57M | avio_context_free(&fuzzed_pb); | 219 | 2.57M | avformat_close_input(&avfmt); | 220 | | | 221 | 2.57M | return 0; | 222 | | | 223 | 1.52M | } |
|