avcodec/ffv1: seperate slice_count from max_slice_count
Fix segfault with too large slice_count Fixes Ticket4879 Signed-off-by: Michael Niedermayer <michael@niedermayer.cc> (cherry picked from commit aa6c43f3fdec8a7518534b9dab20c9eb4be11568) Conflicts: libavcodec/ffv1enc.c
This commit is contained in:
parent
2ef386d0a6
commit
0fb4a85603
@ -101,7 +101,7 @@ av_cold int ffv1_init_slice_state(FFV1Context *f, FFV1Context *fs)
|
|||||||
av_cold int ffv1_init_slices_state(FFV1Context *f)
|
av_cold int ffv1_init_slices_state(FFV1Context *f)
|
||||||
{
|
{
|
||||||
int i, ret;
|
int i, ret;
|
||||||
for (i = 0; i < f->slice_count; i++) {
|
for (i = 0; i < f->max_slice_count; i++) {
|
||||||
FFV1Context *fs = f->slice_context[i];
|
FFV1Context *fs = f->slice_context[i];
|
||||||
if ((ret = ffv1_init_slice_state(f, fs)) < 0)
|
if ((ret = ffv1_init_slice_state(f, fs)) < 0)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
@ -113,10 +113,10 @@ av_cold int ffv1_init_slice_contexts(FFV1Context *f)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
f->slice_count = f->num_h_slices * f->num_v_slices;
|
f->max_slice_count = f->num_h_slices * f->num_v_slices;
|
||||||
av_assert0(f->slice_count > 0);
|
av_assert0(f->max_slice_count > 0);
|
||||||
|
|
||||||
for (i = 0; i < f->slice_count; i++) {
|
for (i = 0; i < f->max_slice_count; i++) {
|
||||||
int sx = i % f->num_h_slices;
|
int sx = i % f->num_h_slices;
|
||||||
int sy = i / f->num_h_slices;
|
int sy = i / f->num_h_slices;
|
||||||
int sxs = f->avctx->width * sx / f->num_h_slices;
|
int sxs = f->avctx->width * sx / f->num_h_slices;
|
||||||
@ -210,7 +210,7 @@ av_cold int ffv1_close(AVCodecContext *avctx)
|
|||||||
ff_thread_release_buffer(avctx, &s->last_picture);
|
ff_thread_release_buffer(avctx, &s->last_picture);
|
||||||
av_frame_free(&s->last_picture.f);
|
av_frame_free(&s->last_picture.f);
|
||||||
|
|
||||||
for (j = 0; j < s->slice_count; j++) {
|
for (j = 0; j < s->max_slice_count; j++) {
|
||||||
FFV1Context *fs = s->slice_context[j];
|
FFV1Context *fs = s->slice_context[j];
|
||||||
for (i = 0; i < s->plane_count; i++) {
|
for (i = 0; i < s->plane_count; i++) {
|
||||||
PlaneContext *p = &fs->plane[i];
|
PlaneContext *p = &fs->plane[i];
|
||||||
@ -224,14 +224,14 @@ av_cold int ffv1_close(AVCodecContext *avctx)
|
|||||||
av_freep(&avctx->stats_out);
|
av_freep(&avctx->stats_out);
|
||||||
for (j = 0; j < s->quant_table_count; j++) {
|
for (j = 0; j < s->quant_table_count; j++) {
|
||||||
av_freep(&s->initial_states[j]);
|
av_freep(&s->initial_states[j]);
|
||||||
for (i = 0; i < s->slice_count; i++) {
|
for (i = 0; i < s->max_slice_count; i++) {
|
||||||
FFV1Context *sf = s->slice_context[i];
|
FFV1Context *sf = s->slice_context[i];
|
||||||
av_freep(&sf->rc_stat2[j]);
|
av_freep(&sf->rc_stat2[j]);
|
||||||
}
|
}
|
||||||
av_freep(&s->rc_stat2[j]);
|
av_freep(&s->rc_stat2[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < s->slice_count; i++)
|
for (i = 0; i < s->max_slice_count; i++)
|
||||||
av_freep(&s->slice_context[i]);
|
av_freep(&s->slice_context[i]);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -117,6 +117,7 @@ typedef struct FFV1Context {
|
|||||||
|
|
||||||
struct FFV1Context *slice_context[MAX_SLICES];
|
struct FFV1Context *slice_context[MAX_SLICES];
|
||||||
int slice_count;
|
int slice_count;
|
||||||
|
int max_slice_count;
|
||||||
int num_v_slices;
|
int num_v_slices;
|
||||||
int num_h_slices;
|
int num_h_slices;
|
||||||
int slice_width;
|
int slice_width;
|
||||||
|
@ -772,6 +772,7 @@ static int read_header(FFV1Context *f)
|
|||||||
av_log(f->avctx, AV_LOG_ERROR, "read_quant_table error\n");
|
av_log(f->avctx, AV_LOG_ERROR, "read_quant_table error\n");
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
|
f->slice_count = f->max_slice_count;
|
||||||
} else if (f->version < 3) {
|
} else if (f->version < 3) {
|
||||||
f->slice_count = get_symbol(c, state, 0);
|
f->slice_count = get_symbol(c, state, 0);
|
||||||
} else {
|
} else {
|
||||||
@ -786,8 +787,8 @@ static int read_header(FFV1Context *f)
|
|||||||
p -= size + trailer;
|
p -= size + trailer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (f->slice_count > (unsigned)MAX_SLICES || f->slice_count <= 0) {
|
if (f->slice_count > (unsigned)MAX_SLICES || f->slice_count <= 0 || f->slice_count > f->max_slice_count) {
|
||||||
av_log(f->avctx, AV_LOG_ERROR, "slice count %d is invalid\n", f->slice_count);
|
av_log(f->avctx, AV_LOG_ERROR, "slice count %d is invalid (max=%d)\n", f->slice_count, f->max_slice_count);
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1010,6 +1011,7 @@ static int init_thread_copy(AVCodecContext *avctx)
|
|||||||
f->picture.f = NULL;
|
f->picture.f = NULL;
|
||||||
f->last_picture.f = NULL;
|
f->last_picture.f = NULL;
|
||||||
f->sample_buffer = NULL;
|
f->sample_buffer = NULL;
|
||||||
|
f->max_slice_count = 0;
|
||||||
f->slice_count = 0;
|
f->slice_count = 0;
|
||||||
|
|
||||||
for (i = 0; i < f->quant_table_count; i++) {
|
for (i = 0; i < f->quant_table_count; i++) {
|
||||||
@ -1085,7 +1087,7 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
|
|||||||
av_assert0(!fdst->sample_buffer);
|
av_assert0(!fdst->sample_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
av_assert1(fdst->slice_count == fsrc->slice_count);
|
av_assert1(fdst->max_slice_count == fsrc->max_slice_count);
|
||||||
|
|
||||||
|
|
||||||
ff_thread_release_buffer(dst, &fdst->picture);
|
ff_thread_release_buffer(dst, &fdst->picture);
|
||||||
|
@ -976,6 +976,7 @@ slices_ok:
|
|||||||
|
|
||||||
if ((ret = ffv1_init_slice_contexts(s)) < 0)
|
if ((ret = ffv1_init_slice_contexts(s)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
s->slice_count = s->max_slice_count;
|
||||||
if ((ret = ffv1_init_slices_state(s)) < 0)
|
if ((ret = ffv1_init_slices_state(s)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -985,7 +986,7 @@ slices_ok:
|
|||||||
if (!avctx->stats_out)
|
if (!avctx->stats_out)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
for (i = 0; i < s->quant_table_count; i++)
|
for (i = 0; i < s->quant_table_count; i++)
|
||||||
for (j = 0; j < s->slice_count; j++) {
|
for (j = 0; j < s->max_slice_count; j++) {
|
||||||
FFV1Context *sf = s->slice_context[j];
|
FFV1Context *sf = s->slice_context[j];
|
||||||
av_assert0(!sf->rc_stat2[i]);
|
av_assert0(!sf->rc_stat2[i]);
|
||||||
sf->rc_stat2[i] = av_mallocz(s->context_count[i] *
|
sf->rc_stat2[i] = av_mallocz(s->context_count[i] *
|
||||||
@ -1209,6 +1210,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
|
|||||||
for (i = 0; i < f->quant_table_count; i++)
|
for (i = 0; i < f->quant_table_count; i++)
|
||||||
memset(f->rc_stat2[i], 0, f->context_count[i] * sizeof(*f->rc_stat2[i]));
|
memset(f->rc_stat2[i], 0, f->context_count[i] * sizeof(*f->rc_stat2[i]));
|
||||||
|
|
||||||
|
av_assert0(f->slice_count == f->max_slice_count);
|
||||||
for (j = 0; j < f->slice_count; j++) {
|
for (j = 0; j < f->slice_count; j++) {
|
||||||
FFV1Context *fs = f->slice_context[j];
|
FFV1Context *fs = f->slice_context[j];
|
||||||
for (i = 0; i < 256; i++) {
|
for (i = 0; i < 256; i++) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user