Mercurial > libavcodec.hg
changeset 8234:4a8f9bbc5e81 libavcodec
Allocate parameter sets sanely instead of using alloc_parameter_set().
Avoids ending up with half initialized parameter sets.
Fixes issue282.
author | michael |
---|---|
date | Mon, 01 Dec 2008 16:04:03 +0000 |
parents | ababfa151ced |
children | 61b5b99f3b77 |
files | h264.c |
diffstat | 1 files changed, 26 insertions(+), 28 deletions(-) [+] |
line wrap: on
line diff
--- a/h264.c Mon Dec 01 06:40:36 2008 +0000 +++ b/h264.c Mon Dec 01 16:04:03 2008 +0000 @@ -6977,26 +6977,6 @@ } } -/** - * Returns and optionally allocates SPS / PPS structures in the supplied array 'vec' - */ -static void * -alloc_parameter_set(H264Context *h, void **vec, const unsigned int id, const unsigned int max, - const size_t size, const char *name) -{ - if(id>=max) { - av_log(h->s.avctx, AV_LOG_ERROR, "%s_id (%d) out of range\n", name, id); - return NULL; - } - - if(!vec[id]) { - vec[id] = av_mallocz(size); - if(vec[id] == NULL) - av_log(h->s.avctx, AV_LOG_ERROR, "cannot allocate memory for %s\n", name); - } - return vec[id]; -} - static inline int decode_seq_parameter_set(H264Context *h){ MpegEncContext * const s = &h->s; int profile_idc, level_idc; @@ -7013,7 +6993,11 @@ level_idc= get_bits(&s->gb, 8); sps_id= get_ue_golomb(&s->gb); - sps = alloc_parameter_set(h, (void **)h->sps_buffers, sps_id, MAX_SPS_COUNT, sizeof(SPS), "sps"); + if(sps_id >= MAX_SPS_COUNT) { + av_log(h->s.avctx, AV_LOG_ERROR, "sps_id (%d) out of range\n", sps_id); + return -1; + } + sps= av_mallocz(sizeof(SPS)); if(sps == NULL) return -1; @@ -7049,7 +7033,7 @@ if(tmp >= FF_ARRAY_ELEMS(sps->offset_for_ref_frame)){ av_log(h->s.avctx, AV_LOG_ERROR, "poc_cycle_length overflow %u\n", tmp); - return -1; + goto fail; } sps->poc_cycle_length= tmp; @@ -7057,13 +7041,13 @@ sps->offset_for_ref_frame[i]= get_se_golomb(&s->gb); }else if(sps->poc_type != 2){ av_log(h->s.avctx, AV_LOG_ERROR, "illegal POC type %d\n", sps->poc_type); - return -1; + goto fail; } tmp= get_ue_golomb(&s->gb); if(tmp > MAX_PICTURE_COUNT-2 || tmp >= 32){ av_log(h->s.avctx, AV_LOG_ERROR, "too many reference frames\n"); - return -1; + goto fail; } sps->ref_frame_count= tmp; sps->gaps_in_frame_num_allowed_flag= get_bits1(&s->gb); @@ -7072,7 +7056,7 @@ if(mb_width >= INT_MAX/16 || mb_height >= INT_MAX/16 || avcodec_check_dimensions(NULL, 16*mb_width, 16*mb_height)){ av_log(h->s.avctx, AV_LOG_ERROR, "mb_width/height overflow\n"); - return -1; + goto fail; } sps->mb_width = mb_width; sps->mb_height= mb_height; @@ -7126,7 +7110,12 @@ ((const char*[]){"Gray","420","422","444"})[sps->chroma_format_idc] ); } + av_free(h->sps_buffers[sps_id]); + h->sps_buffers[sps_id]= sps; return 0; +fail: + av_free(sps); + return -1; } static void @@ -7142,15 +7131,19 @@ unsigned int tmp, pps_id= get_ue_golomb(&s->gb); PPS *pps; - pps = alloc_parameter_set(h, (void **)h->pps_buffers, pps_id, MAX_PPS_COUNT, sizeof(PPS), "pps"); - if(pps == NULL) + if(pps_id >= MAX_PPS_COUNT) { + av_log(h->s.avctx, AV_LOG_ERROR, "pps_id (%d) out of range\n", pps_id); return -1; + } tmp= get_ue_golomb(&s->gb); if(tmp>=MAX_SPS_COUNT || h->sps_buffers[tmp] == NULL){ av_log(h->s.avctx, AV_LOG_ERROR, "sps_id out of range\n"); return -1; } + pps= av_mallocz(sizeof(PPS)); + if(pps == NULL) + return -1; pps->sps_id= tmp; pps->cabac= get_bits1(&s->gb); @@ -7198,7 +7191,7 @@ if(pps->ref_count[0]-1 > 32-1 || pps->ref_count[1]-1 > 32-1){ av_log(h->s.avctx, AV_LOG_ERROR, "reference overflow (pps)\n"); pps->ref_count[0]= pps->ref_count[1]= 1; - return -1; + goto fail; } pps->weighted_pred= get_bits1(&s->gb); @@ -7243,7 +7236,12 @@ ); } + av_free(h->pps_buffers[pps_id]); + h->pps_buffers[pps_id]= pps; return 0; +fail: + av_free(pps); + return -1; } /**