From caaeb15318dbdd38344f15a8919540f188de5c46 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 16 Sep 2014 18:11:00 +0200 Subject: demux: gracefully handle packet allocation failures Now the packet allocation functions can fail. --- demux/demux_lavf.c | 12 +++++++++--- demux/demux_mf.c | 10 ++++++---- demux/demux_mkv.c | 10 +++++++++- demux/demux_raw.c | 5 +++++ demux/demux_tv.c | 24 ++++++++++++++---------- demux/packet.c | 18 +++++++++++------- sub/dec_sub.c | 6 ++++-- 7 files changed, 58 insertions(+), 27 deletions(-) diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index ce945a2c4b..750f0f09f3 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -479,9 +479,11 @@ static void handle_stream(demuxer_t *demuxer, int i) if (st->disposition & AV_DISPOSITION_ATTACHED_PIC) { sh->attached_picture = new_demux_packet_from(st->attached_pic.data, st->attached_pic.size); - sh->attached_picture->pts = 0; - talloc_steal(sh, sh->attached_picture); - sh->attached_picture->keyframe = true; + if (sh->attached_picture) { + sh->attached_picture->pts = 0; + talloc_steal(sh, sh->attached_picture); + sh->attached_picture->keyframe = true; + } } sh->format = codec->codec_tag; @@ -820,6 +822,10 @@ static int demux_lavf_fill_buffer(demuxer_t *demux) } struct demux_packet *dp = new_demux_packet_from_avpacket(pkt); + if (!dp) { + av_free_packet(pkt); + return 1; + } if (pkt->pts != AV_NOPTS_VALUE) dp->pts = pkt->pts * av_q2d(st->time_base); diff --git a/demux/demux_mf.c b/demux/demux_mf.c index c0e4cd7757..fa42f52782 100644 --- a/demux/demux_mf.c +++ b/demux/demux_mf.c @@ -77,10 +77,12 @@ static int demux_mf_fill_buffer(demuxer_t *demuxer) bstr data = stream_read_complete(stream, NULL, MF_MAX_FILE_SIZE); if (data.len) { demux_packet_t *dp = new_demux_packet(data.len); - memcpy(dp->buffer, data.start, data.len); - dp->pts = mf->curr_frame / mf->sh->fps; - dp->keyframe = true; - demux_add_packet(demuxer->streams[0], dp); + if (dp) { + memcpy(dp->buffer, data.start, data.len); + dp->pts = mf->curr_frame / mf->sh->fps; + dp->keyframe = true; + demux_add_packet(demuxer->streams[0], dp); + } } talloc_free(data.start); } diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 978e367ec5..c20a1aa999 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -1978,6 +1978,8 @@ static void handle_realvideo(demuxer_t *demuxer, mkv_track_t *track, int64_t timestamp = mkv_d->last_pts * 1000; dp = new_demux_packet_from(data.start, data.len); + if (!dp) + return; if (mkv_d->v_skip_to_keyframe) { dp->pts = mkv_d->last_pts; @@ -2096,6 +2098,8 @@ static void handle_realaudio(demuxer_t *demuxer, mkv_track_t *track, for (int x = 0; x < sph * w / apk_usize; x++) { dp = new_demux_packet_from(track->audio_buf + x * apk_usize, apk_usize); + if (!dp) + goto error; /* Put timestamp only on packets that correspond to original * audio packets in file */ dp->pts = (x * apk_usize % w) ? MP_NOPTS_VALUE : @@ -2107,6 +2111,8 @@ static void handle_realaudio(demuxer_t *demuxer, mkv_track_t *track, } } else { // Not a codec that requires reordering dp = new_demux_packet_from(buffer, size); + if (!dp) + goto error; if (track->ra_pts == mkv_d->last_pts && !mkv_d->a_skip_to_keyframe) dp->pts = MP_NOPTS_VALUE; else @@ -2119,7 +2125,7 @@ static void handle_realaudio(demuxer_t *demuxer, mkv_track_t *track, } return; error: - MP_ERR(demuxer, "RealAudio decrypting error.\n"); + MP_ERR(demuxer, "RealAudio packet extraction or decryption error.\n"); } static void mkv_seek_reset(demuxer_t *demuxer) @@ -2424,6 +2430,8 @@ static int handle_block(demuxer_t *demuxer, struct block_info *block_info) while (raw.start && mkv_parse_packet(track, &raw, &buffer)) { demux_packet_t *dp = new_demux_packet_from(buffer.start, buffer.len); + if (!dp) + break; dp->keyframe = keyframe; /* If default_duration is 0, assume no pts value is known * for packets after the first one (rather than all pts diff --git a/demux/demux_raw.c b/demux/demux_raw.c index 4388900ce6..288a1c931c 100644 --- a/demux/demux_raw.c +++ b/demux/demux_raw.c @@ -227,6 +227,11 @@ static int raw_fill_buffer(demuxer_t *demuxer) return 0; struct demux_packet *dp = new_demux_packet(p->frame_size * p->read_frames); + if (!dp) { + MP_ERR(demuxer, "Can't read packet.\n"); + return 1; + } + dp->pos = stream_tell(demuxer->stream); dp->pts = (dp->pos / p->frame_size) / p->frame_rate; diff --git a/demux/demux_tv.c b/demux/demux_tv.c index f0ee9793e3..fe7584a387 100644 --- a/demux/demux_tv.c +++ b/demux/demux_tv.c @@ -204,26 +204,30 @@ static int demux_tv_fill_buffer(demuxer_t *demux) if (want_audio && tvh->tv_param->audio && tvh->functions->control(tvh->priv, TVI_CONTROL_IS_AUDIO, 0) == TVI_CONTROL_TRUE) - { + { len = tvh->functions->get_audio_framesize(tvh->priv); dp=new_demux_packet(len); - dp->keyframe = true; - dp->pts=tvh->functions->grab_audio_frame(tvh->priv, dp->buffer,len); - demux_add_packet(want_audio, dp); + if (dp) { + dp->keyframe = true; + dp->pts=tvh->functions->grab_audio_frame(tvh->priv, dp->buffer,len); + demux_add_packet(want_audio, dp); } + } /* ================== ADD VIDEO PACKET =================== */ if (want_video && tvh->functions->control(tvh->priv, TVI_CONTROL_IS_VIDEO, 0) == TVI_CONTROL_TRUE) - { - len = tvh->functions->get_video_framesize(tvh->priv); + { + len = tvh->functions->get_video_framesize(tvh->priv); dp=new_demux_packet(len); - dp->keyframe = true; - dp->pts=tvh->functions->grab_video_frame(tvh->priv, dp->buffer, len); - demux_add_packet(want_video, dp); - } + if (dp) { + dp->keyframe = true; + dp->pts=tvh->functions->grab_video_frame(tvh->priv, dp->buffer, len); + demux_add_packet(want_video, dp); + } + } if (tvh->tv_param->scan) tv_scan(tvh); return 1; diff --git a/demux/packet.c b/demux/packet.c index 2008113600..959c707732 100644 --- a/demux/packet.c +++ b/demux/packet.c @@ -37,10 +37,8 @@ static void packet_destroy(void *ptr) // does not allow it, but we do it to simplify new_demux_packet(). struct demux_packet *new_demux_packet_from_avpacket(struct AVPacket *avpkt) { - if (avpkt->size > 1000000000) { - fprintf(stderr, "Attempt to allocate demux packet over 1 GB!\n"); - abort(); - } + if (avpkt->size > 1000000000) + return NULL; struct demux_packet *dp = talloc(NULL, struct demux_packet); talloc_set_destructor(dp, packet_destroy); *dp = (struct demux_packet) { @@ -61,8 +59,9 @@ struct demux_packet *new_demux_packet_from_avpacket(struct AVPacket *avpkt) r = av_new_packet(dp->avpacket, avpkt->size); } if (r < 0) { - fprintf(stderr, "Out of memory when referencing packet.\n"); - abort(); + *dp->avpacket = (AVPacket){0}; + talloc_free(dp); + return NULL; } dp->buffer = dp->avpacket->data; dp->len = dp->avpacket->size; @@ -72,13 +71,16 @@ struct demux_packet *new_demux_packet_from_avpacket(struct AVPacket *avpkt) // Input data doesn't need to be padded. struct demux_packet *new_demux_packet_from(void *data, size_t len) { + if (len > INT_MAX) + return NULL; AVPacket pkt = { .data = data, .size = len }; return new_demux_packet_from_avpacket(&pkt); } struct demux_packet *new_demux_packet(size_t len) { - assert(len <= INT_MAX); + if (len > INT_MAX) + return NULL; AVPacket pkt = { .data = NULL, .size = len }; return new_demux_packet_from_avpacket(&pkt); } @@ -104,6 +106,8 @@ struct demux_packet *demux_copy_packet(struct demux_packet *dp) // Some packets might be not created by new_demux_packet*(). new = new_demux_packet_from(dp->buffer, dp->len); } + if (!new) + return NULL; new->pts = dp->pts; new->dts = dp->dts; new->duration = dp->duration; diff --git a/sub/dec_sub.c b/sub/dec_sub.c index cc608c3ca5..7a0f5eb408 100644 --- a/sub/dec_sub.c +++ b/sub/dec_sub.c @@ -400,8 +400,10 @@ static void add_sub_list(struct dec_sub *sub, int at, struct packet_list *subs) static void add_packet(struct packet_list *subs, struct demux_packet *pkt) { pkt = demux_copy_packet(pkt); - talloc_steal(subs, pkt); - MP_TARRAY_APPEND(subs, subs->packets, subs->num_packets, pkt); + if (pkt) { + talloc_steal(subs, pkt); + MP_TARRAY_APPEND(subs, subs->packets, subs->num_packets, pkt); + } } // Read all packets from the demuxer and decode/add them. Returns false if -- cgit v1.2.3