History

lavf: sanity check size in av_get/append_packet().

To avoid allocating ridiculous amounts of memory for corrupted files, read the input in chunks limited to filesize or an arbitrary large amount when that is not known (chosen to be 50M).

Anton Khirnov committed 13 years ago

Commit aa3c7791 parent ca6c3f21 file · +49 −19Browse files

Unified · Split

libavformat/utils.c+49−19
@@ -214,38 +214,68 @@ AVInputFormat *av_find_input_format(const char *short_name) · 213 unmodified lines
214214 return NULL;
215215 }
216216
217+/* an arbitrarily chosen "sane" max packet size -- 50M */
218+#define SANE_CHUNK_SIZE (50000000)
217219
218−int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
220+/*
221+ * Read the data in sane-sized chunks and append to pkt.
222+ * Return the number of bytes read or an error.
223+ */
224+static int append_packet_chunked(AVIOContext *s, AVPacket *pkt, int size)
219225 {
220− int ret= av_new_packet(pkt, size);
226+ int64_t chunk_size = size;
227+ int orig_pos = pkt->pos; // av_grow_packet might reset pos
228+ int orig_size = pkt->size;
229+ int ret = 0;
221230
222− if(ret<0)
223− return ret;
231+ do {
232+ int prev_size = pkt->size;
233+ int read_size;
234+
235+ /*
236+ * When the caller requests a lot of data, limit it to the amount left
237+ * in file or SANE_CHUNK_SIZE when it is not known
238+ */
239+ if (size > SANE_CHUNK_SIZE) {
240+ int64_t filesize = avio_size(s) - avio_tell(s);
241+ chunk_size = FFMAX(filesize, SANE_CHUNK_SIZE);
242+ }
243+ read_size = FFMIN(size, chunk_size);
244+
245+ ret = av_grow_packet(pkt, read_size);
246+ if (ret < 0)
247+ break;
248+
249+ ret = avio_read(s, pkt->data + prev_size, read_size);
250+ if (ret != read_size) {
251+ av_shrink_packet(pkt, prev_size + FFMAX(ret, 0));
252+ break;
253+ }
224254
225− pkt->pos= avio_tell(s);
255+ size -= read_size;
256+ } while (size > 0);
226257
227− ret= avio_read(s, pkt->data, size);
228− if(ret<=0)
258+ pkt->pos = orig_pos;
259+ if (!pkt->size)
229260 av_free_packet(pkt);
230− else
231− av_shrink_packet(pkt, ret);
261+ return pkt->size > orig_size ? pkt->size - orig_size : ret;
262+}
232263
233− return ret;
264+int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
265+{
266+ av_init_packet(pkt);
267+ pkt->data = NULL;
268+ pkt->size = 0;
269+ pkt->pos = avio_tell(s);
270+
271+ return append_packet_chunked(s, pkt, size);
234272 }
235273
236274 int av_append_packet(AVIOContext *s, AVPacket *pkt, int size)
237275 {
238− int ret;
239− int old_size;
240276 if (!pkt->size)
241277 return av_get_packet(s, pkt, size);
242− old_size = pkt->size;
243− ret = av_grow_packet(pkt, size);
244− if (ret < 0)
245− return ret;
246− ret = avio_read(s, pkt->data + old_size, size);
247− av_shrink_packet(pkt, old_size + FFMAX(ret, 0));
248− return ret;
278+ return append_packet_chunked(s, pkt, size);
249279 }
250280
251281

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t