Commit 8ab80707 authored by Michael Niedermayer's avatar Michael Niedermayer

avcodec/utils: fix sizeof(AVFrame) dependence in avcodec_encode_audio2()

This is a bit tricky, we allocate a correctly sized AVFrame but then only
copy the compile time AVFrame size, this is to ensure that user applications
which do not use the correct av frame API dont end with out of array reads.
Note, applications using the correct API have set extended_data and the
changed code will never be executed for them.
Signed-off-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parent aa1f3801
...@@ -1615,7 +1615,7 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, ...@@ -1615,7 +1615,7 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx,
const AVFrame *frame, const AVFrame *frame,
int *got_packet_ptr) int *got_packet_ptr)
{ {
AVFrame tmp; AVFrame *extended_frame = NULL;
AVFrame *padded_frame = NULL; AVFrame *padded_frame = NULL;
int ret; int ret;
AVPacket user_pkt = *avpkt; AVPacket user_pkt = *avpkt;
...@@ -1640,9 +1640,13 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, ...@@ -1640,9 +1640,13 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx,
} }
av_log(avctx, AV_LOG_WARNING, "extended_data is not set.\n"); av_log(avctx, AV_LOG_WARNING, "extended_data is not set.\n");
tmp = *frame; extended_frame = av_frame_alloc();
tmp.extended_data = tmp.data; if (!extended_frame)
frame = &tmp; return AVERROR(ENOMEM);
memcpy(extended_frame, frame, sizeof(AVFrame));
extended_frame->extended_data = extended_frame->data;
frame = extended_frame;
} }
/* check for valid frame size */ /* check for valid frame size */
...@@ -1650,14 +1654,15 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, ...@@ -1650,14 +1654,15 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx,
if (avctx->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) { if (avctx->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) {
if (frame->nb_samples > avctx->frame_size) { if (frame->nb_samples > avctx->frame_size) {
av_log(avctx, AV_LOG_ERROR, "more samples than frame size (avcodec_encode_audio2)\n"); av_log(avctx, AV_LOG_ERROR, "more samples than frame size (avcodec_encode_audio2)\n");
return AVERROR(EINVAL); ret = AVERROR(EINVAL);
goto end;
} }
} else if (!(avctx->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) { } else if (!(avctx->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) {
if (frame->nb_samples < avctx->frame_size && if (frame->nb_samples < avctx->frame_size &&
!avctx->internal->last_audio_frame) { !avctx->internal->last_audio_frame) {
ret = pad_last_frame(avctx, &padded_frame, frame); ret = pad_last_frame(avctx, &padded_frame, frame);
if (ret < 0) if (ret < 0)
return ret; goto end;
frame = padded_frame; frame = padded_frame;
avctx->internal->last_audio_frame = 1; avctx->internal->last_audio_frame = 1;
...@@ -1729,6 +1734,7 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, ...@@ -1729,6 +1734,7 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx,
end: end:
av_frame_free(&padded_frame); av_frame_free(&padded_frame);
av_free(extended_frame);
return ret; return ret;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment