Mercurial > libavcodec.hg
comparison h264.c @ 4362:0271b214458b libavcodec
harden h264 decoding to prevent some crashes when input data is corrupted.
Patch by Frank %eucloid A gmail P com%
date: Jan 18, 2007 6:48 PM
subject: Re: [Ffmpeg-devel] h264, protection against corrupted data (second try patch)
AND
date: Jan 17, 2007 8:22 PM
subject: [Ffmpeg-devel] h264, protection against corrupted data
this also fixes a possible security issue (the sps and pps ids where not checked,
then used as index into an array of sps/pps structs which was then filled with data from the bitstream)
author | gpoirier |
---|---|
date | Fri, 19 Jan 2007 09:37:04 +0000 |
parents | d18568fb0187 |
children | 9b7662fa4905 |
comparison
equal
deleted
inserted
replaced
4361:f80a3b6c6f00 | 4362:0271b214458b |
---|---|
115 | 115 |
116 /** | 116 /** |
117 * Picture parameter set | 117 * Picture parameter set |
118 */ | 118 */ |
119 typedef struct PPS{ | 119 typedef struct PPS{ |
120 int sps_id; | 120 unsigned int sps_id; |
121 int cabac; ///< entropy_coding_mode_flag | 121 int cabac; ///< entropy_coding_mode_flag |
122 int pic_order_present; ///< pic_order_present_flag | 122 int pic_order_present; ///< pic_order_present_flag |
123 int slice_group_count; ///< num_slice_groups_minus1 + 1 | 123 int slice_group_count; ///< num_slice_groups_minus1 + 1 |
124 int mb_slice_group_map_type; | 124 int mb_slice_group_map_type; |
125 int ref_count[2]; ///< num_ref_idx_l0/1_active_minus1 + 1 | 125 int ref_count[2]; ///< num_ref_idx_l0/1_active_minus1 + 1 |
1778 } | 1778 } |
1779 | 1779 |
1780 h->rbsp_buffer= av_fast_realloc(h->rbsp_buffer, &h->rbsp_buffer_size, length); | 1780 h->rbsp_buffer= av_fast_realloc(h->rbsp_buffer, &h->rbsp_buffer_size, length); |
1781 dst= h->rbsp_buffer; | 1781 dst= h->rbsp_buffer; |
1782 | 1782 |
1783 if (dst == NULL){ | |
1784 return NULL; | |
1785 } | |
1786 | |
1783 //printf("decoding esc\n"); | 1787 //printf("decoding esc\n"); |
1784 si=di=0; | 1788 si=di=0; |
1785 while(si<length){ | 1789 while(si<length){ |
1786 //remove escapes (very rare 1:2^22) | 1790 //remove escapes (very rare 1:2^22) |
1787 if(si+2<length && src[si]==0 && src[si+1]==0 && src[si+2]<=3){ | 1791 if(si+2<length && src[si]==0 && src[si+1]==0 && src[si+2]<=3){ |
3948 if(i>=0) | 3952 if(i>=0) |
3949 ref->pic_id= ref->frame_num; | 3953 ref->pic_id= ref->frame_num; |
3950 }else{ | 3954 }else{ |
3951 pic_id= get_ue_golomb(&s->gb); //long_term_pic_idx | 3955 pic_id= get_ue_golomb(&s->gb); //long_term_pic_idx |
3952 ref = h->long_ref[pic_id]; | 3956 ref = h->long_ref[pic_id]; |
3953 ref->pic_id= pic_id; | 3957 if(ref){ |
3954 assert(ref->reference == 3); | 3958 ref->pic_id= pic_id; |
3955 assert(ref->long_ref); | 3959 assert(ref->reference == 3); |
3956 i=0; | 3960 assert(ref->long_ref); |
3961 i=0; | |
3962 }else{ | |
3963 i=-1; | |
3964 } | |
3957 } | 3965 } |
3958 | 3966 |
3959 if (i < 0) { | 3967 if (i < 0) { |
3960 av_log(h->s.avctx, AV_LOG_ERROR, "reference picture missing during reorder\n"); | 3968 av_log(h->s.avctx, AV_LOG_ERROR, "reference picture missing during reorder\n"); |
3961 memset(&h->ref_list[list][index], 0, sizeof(Picture)); //FIXME | 3969 memset(&h->ref_list[list][index], 0, sizeof(Picture)); //FIXME |
4257 case MMCO_SHORT2LONG: | 4265 case MMCO_SHORT2LONG: |
4258 pic= remove_long(h, mmco[i].long_index); | 4266 pic= remove_long(h, mmco[i].long_index); |
4259 if(pic) unreference_pic(h, pic); | 4267 if(pic) unreference_pic(h, pic); |
4260 | 4268 |
4261 h->long_ref[ mmco[i].long_index ]= remove_short(h, mmco[i].short_frame_num); | 4269 h->long_ref[ mmco[i].long_index ]= remove_short(h, mmco[i].short_frame_num); |
4262 h->long_ref[ mmco[i].long_index ]->long_ref=1; | 4270 if (h->long_ref[ mmco[i].long_index ]){ |
4263 h->long_ref_count++; | 4271 h->long_ref[ mmco[i].long_index ]->long_ref=1; |
4272 h->long_ref_count++; | |
4273 } | |
4264 break; | 4274 break; |
4265 case MMCO_LONG2UNUSED: | 4275 case MMCO_LONG2UNUSED: |
4266 pic= remove_long(h, mmco[i].long_index); | 4276 pic= remove_long(h, mmco[i].long_index); |
4267 if(pic) | 4277 if(pic) |
4268 unreference_pic(h, pic); | 4278 unreference_pic(h, pic); |
4288 } | 4298 } |
4289 break; | 4299 break; |
4290 case MMCO_RESET: | 4300 case MMCO_RESET: |
4291 while(h->short_ref_count){ | 4301 while(h->short_ref_count){ |
4292 pic= remove_short(h, h->short_ref[0]->frame_num); | 4302 pic= remove_short(h, h->short_ref[0]->frame_num); |
4293 unreference_pic(h, pic); | 4303 if(pic) unreference_pic(h, pic); |
4294 } | 4304 } |
4295 for(j = 0; j < 16; j++) { | 4305 for(j = 0; j < 16; j++) { |
4296 pic= remove_long(h, j); | 4306 pic= remove_long(h, j); |
4297 if(pic) unreference_pic(h, pic); | 4307 if(pic) unreference_pic(h, pic); |
4298 } | 4308 } |
4471 * decodes a slice header. | 4481 * decodes a slice header. |
4472 * this will allso call MPV_common_init() and frame_start() as needed | 4482 * this will allso call MPV_common_init() and frame_start() as needed |
4473 */ | 4483 */ |
4474 static int decode_slice_header(H264Context *h){ | 4484 static int decode_slice_header(H264Context *h){ |
4475 MpegEncContext * const s = &h->s; | 4485 MpegEncContext * const s = &h->s; |
4476 int first_mb_in_slice, pps_id; | 4486 int first_mb_in_slice; |
4487 unsigned int pps_id; | |
4477 int num_ref_idx_active_override_flag; | 4488 int num_ref_idx_active_override_flag; |
4478 static const uint8_t slice_type_map[5]= {P_TYPE, B_TYPE, I_TYPE, SP_TYPE, SI_TYPE}; | 4489 static const uint8_t slice_type_map[5]= {P_TYPE, B_TYPE, I_TYPE, SP_TYPE, SI_TYPE}; |
4479 int slice_type; | 4490 int slice_type; |
4480 int default_ref_list_done = 0; | 4491 int default_ref_list_done = 0; |
4481 | 4492 |
4503 h->slice_type= slice_type; | 4514 h->slice_type= slice_type; |
4504 | 4515 |
4505 s->pict_type= h->slice_type; // to make a few old func happy, it's wrong though | 4516 s->pict_type= h->slice_type; // to make a few old func happy, it's wrong though |
4506 | 4517 |
4507 pps_id= get_ue_golomb(&s->gb); | 4518 pps_id= get_ue_golomb(&s->gb); |
4508 if(pps_id>255){ | 4519 if(pps_id>=MAX_PPS_COUNT){ |
4509 av_log(h->s.avctx, AV_LOG_ERROR, "pps_id out of range\n"); | 4520 av_log(h->s.avctx, AV_LOG_ERROR, "pps_id out of range\n"); |
4510 return -1; | 4521 return -1; |
4511 } | 4522 } |
4512 h->pps= h->pps_buffer[pps_id]; | 4523 h->pps= h->pps_buffer[pps_id]; |
4513 if(h->pps.slice_group_count == 0){ | 4524 if(h->pps.slice_group_count == 0){ |
4519 if(h->sps.log2_max_frame_num == 0){ | 4530 if(h->sps.log2_max_frame_num == 0){ |
4520 av_log(h->s.avctx, AV_LOG_ERROR, "non existing SPS referenced\n"); | 4531 av_log(h->s.avctx, AV_LOG_ERROR, "non existing SPS referenced\n"); |
4521 return -1; | 4532 return -1; |
4522 } | 4533 } |
4523 | 4534 |
4524 if(h->dequant_coeff_pps != pps_id){ | 4535 if(h->dequant_coeff_pps != (int)pps_id){ |
4525 h->dequant_coeff_pps = pps_id; | 4536 h->dequant_coeff_pps = (int)pps_id; |
4526 init_dequant_tables(h); | 4537 init_dequant_tables(h); |
4527 } | 4538 } |
4528 | 4539 |
4529 s->mb_width= h->sps.mb_width; | 4540 s->mb_width= h->sps.mb_width; |
4530 s->mb_height= h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag); | 4541 s->mb_height= h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag); |
4760 | 4771 |
4761 h->emu_edge_width= (s->flags&CODEC_FLAG_EMU_EDGE) ? 0 : 16; | 4772 h->emu_edge_width= (s->flags&CODEC_FLAG_EMU_EDGE) ? 0 : 16; |
4762 h->emu_edge_height= FRAME_MBAFF ? 0 : h->emu_edge_width; | 4773 h->emu_edge_height= FRAME_MBAFF ? 0 : h->emu_edge_width; |
4763 | 4774 |
4764 if(s->avctx->debug&FF_DEBUG_PICT_INFO){ | 4775 if(s->avctx->debug&FF_DEBUG_PICT_INFO){ |
4765 av_log(h->s.avctx, AV_LOG_DEBUG, "slice:%d %s mb:%d %c pps:%d frame:%d poc:%d/%d ref:%d/%d qp:%d loop:%d:%d:%d weight:%d%s\n", | 4776 av_log(h->s.avctx, AV_LOG_DEBUG, "slice:%d %s mb:%d %c pps:%u frame:%d poc:%d/%d ref:%d/%d qp:%d loop:%d:%d:%d weight:%d%s\n", |
4766 h->slice_num, | 4777 h->slice_num, |
4767 (s->picture_structure==PICT_FRAME ? "F" : s->picture_structure==PICT_TOP_FIELD ? "T" : "B"), | 4778 (s->picture_structure==PICT_FRAME ? "F" : s->picture_structure==PICT_TOP_FIELD ? "T" : "B"), |
4768 first_mb_in_slice, | 4779 first_mb_in_slice, |
4769 av_get_pict_type_char(h->slice_type), | 4780 av_get_pict_type_char(h->slice_type), |
4770 pps_id, h->frame_num, | 4781 pps_id, h->frame_num, |
7670 } | 7681 } |
7671 | 7682 |
7672 static inline int decode_seq_parameter_set(H264Context *h){ | 7683 static inline int decode_seq_parameter_set(H264Context *h){ |
7673 MpegEncContext * const s = &h->s; | 7684 MpegEncContext * const s = &h->s; |
7674 int profile_idc, level_idc; | 7685 int profile_idc, level_idc; |
7675 int sps_id, i; | 7686 unsigned int sps_id; |
7687 int i; | |
7676 SPS *sps; | 7688 SPS *sps; |
7677 | 7689 |
7678 profile_idc= get_bits(&s->gb, 8); | 7690 profile_idc= get_bits(&s->gb, 8); |
7679 get_bits1(&s->gb); //constraint_set0_flag | 7691 get_bits1(&s->gb); //constraint_set0_flag |
7680 get_bits1(&s->gb); //constraint_set1_flag | 7692 get_bits1(&s->gb); //constraint_set1_flag |
7681 get_bits1(&s->gb); //constraint_set2_flag | 7693 get_bits1(&s->gb); //constraint_set2_flag |
7682 get_bits1(&s->gb); //constraint_set3_flag | 7694 get_bits1(&s->gb); //constraint_set3_flag |
7683 get_bits(&s->gb, 4); // reserved | 7695 get_bits(&s->gb, 4); // reserved |
7684 level_idc= get_bits(&s->gb, 8); | 7696 level_idc= get_bits(&s->gb, 8); |
7685 sps_id= get_ue_golomb(&s->gb); | 7697 sps_id= get_ue_golomb(&s->gb); |
7698 | |
7699 if (sps_id >= MAX_SPS_COUNT){ | |
7700 // ok it has gone out of hand, someone is sending us bad stuff. | |
7701 av_log(h->s.avctx, AV_LOG_ERROR, "illegal sps_id (%d)\n", sps_id); | |
7702 return -1; | |
7703 } | |
7686 | 7704 |
7687 sps= &h->sps_buffer[ sps_id ]; | 7705 sps= &h->sps_buffer[ sps_id ]; |
7688 sps->profile_idc= profile_idc; | 7706 sps->profile_idc= profile_idc; |
7689 sps->level_idc= level_idc; | 7707 sps->level_idc= level_idc; |
7690 | 7708 |
7762 sps->vui_parameters_present_flag= get_bits1(&s->gb); | 7780 sps->vui_parameters_present_flag= get_bits1(&s->gb); |
7763 if( sps->vui_parameters_present_flag ) | 7781 if( sps->vui_parameters_present_flag ) |
7764 decode_vui_parameters(h, sps); | 7782 decode_vui_parameters(h, sps); |
7765 | 7783 |
7766 if(s->avctx->debug&FF_DEBUG_PICT_INFO){ | 7784 if(s->avctx->debug&FF_DEBUG_PICT_INFO){ |
7767 av_log(h->s.avctx, AV_LOG_DEBUG, "sps:%d profile:%d/%d poc:%d ref:%d %dx%d %s %s crop:%d/%d/%d/%d %s\n", | 7785 av_log(h->s.avctx, AV_LOG_DEBUG, "sps:%u profile:%d/%d poc:%d ref:%d %dx%d %s %s crop:%d/%d/%d/%d %s\n", |
7768 sps_id, sps->profile_idc, sps->level_idc, | 7786 sps_id, sps->profile_idc, sps->level_idc, |
7769 sps->poc_type, | 7787 sps->poc_type, |
7770 sps->ref_frame_count, | 7788 sps->ref_frame_count, |
7771 sps->mb_width, sps->mb_height, | 7789 sps->mb_width, sps->mb_height, |
7772 sps->frame_mbs_only_flag ? "FRM" : (sps->mb_aff ? "MB-AFF" : "PIC-AFF"), | 7790 sps->frame_mbs_only_flag ? "FRM" : (sps->mb_aff ? "MB-AFF" : "PIC-AFF"), |
7779 return 0; | 7797 return 0; |
7780 } | 7798 } |
7781 | 7799 |
7782 static inline int decode_picture_parameter_set(H264Context *h, int bit_length){ | 7800 static inline int decode_picture_parameter_set(H264Context *h, int bit_length){ |
7783 MpegEncContext * const s = &h->s; | 7801 MpegEncContext * const s = &h->s; |
7784 int pps_id= get_ue_golomb(&s->gb); | 7802 unsigned int pps_id= get_ue_golomb(&s->gb); |
7785 PPS *pps= &h->pps_buffer[pps_id]; | 7803 PPS *pps; |
7804 | |
7805 if(pps_id>=MAX_PPS_COUNT){ | |
7806 av_log(h->s.avctx, AV_LOG_ERROR, "pps_id out of range\n"); | |
7807 return -1; | |
7808 } | |
7809 pps = &h->pps_buffer[pps_id]; | |
7786 | 7810 |
7787 pps->sps_id= get_ue_golomb(&s->gb); | 7811 pps->sps_id= get_ue_golomb(&s->gb); |
7788 pps->cabac= get_bits1(&s->gb); | 7812 pps->cabac= get_bits1(&s->gb); |
7789 pps->pic_order_present= get_bits1(&s->gb); | 7813 pps->pic_order_present= get_bits1(&s->gb); |
7790 pps->slice_group_count= get_ue_golomb(&s->gb) + 1; | 7814 pps->slice_group_count= get_ue_golomb(&s->gb) + 1; |
7851 decode_scaling_matrices(h, &h->sps_buffer[pps->sps_id], pps, 0, pps->scaling_matrix4, pps->scaling_matrix8); | 7875 decode_scaling_matrices(h, &h->sps_buffer[pps->sps_id], pps, 0, pps->scaling_matrix4, pps->scaling_matrix8); |
7852 get_se_golomb(&s->gb); //second_chroma_qp_index_offset | 7876 get_se_golomb(&s->gb); //second_chroma_qp_index_offset |
7853 } | 7877 } |
7854 | 7878 |
7855 if(s->avctx->debug&FF_DEBUG_PICT_INFO){ | 7879 if(s->avctx->debug&FF_DEBUG_PICT_INFO){ |
7856 av_log(h->s.avctx, AV_LOG_DEBUG, "pps:%d sps:%d %s slice_groups:%d ref:%d/%d %s qp:%d/%d/%d %s %s %s %s\n", | 7880 av_log(h->s.avctx, AV_LOG_DEBUG, "pps:%u sps:%u %s slice_groups:%d ref:%d/%d %s qp:%d/%d/%d %s %s %s %s\n", |
7857 pps_id, pps->sps_id, | 7881 pps_id, pps->sps_id, |
7858 pps->cabac ? "CABAC" : "CAVLC", | 7882 pps->cabac ? "CABAC" : "CAVLC", |
7859 pps->slice_group_count, | 7883 pps->slice_group_count, |
7860 pps->ref_count[0], pps->ref_count[1], | 7884 pps->ref_count[0], pps->ref_count[1], |
7861 pps->weighted_pred ? "weighted" : "", | 7885 pps->weighted_pred ? "weighted" : "", |
7985 if(h->is_avc) { | 8009 if(h->is_avc) { |
7986 if(buf_index >= buf_size) break; | 8010 if(buf_index >= buf_size) break; |
7987 nalsize = 0; | 8011 nalsize = 0; |
7988 for(i = 0; i < h->nal_length_size; i++) | 8012 for(i = 0; i < h->nal_length_size; i++) |
7989 nalsize = (nalsize << 8) | buf[buf_index++]; | 8013 nalsize = (nalsize << 8) | buf[buf_index++]; |
7990 if(nalsize <= 1){ | 8014 if(nalsize <= 1 || nalsize > buf_size){ |
7991 if(nalsize == 1){ | 8015 if(nalsize == 1){ |
7992 buf_index++; | 8016 buf_index++; |
7993 continue; | 8017 continue; |
7994 }else{ | 8018 }else{ |
7995 av_log(h->s.avctx, AV_LOG_ERROR, "AVC: nal size %d\n", nalsize); | 8019 av_log(h->s.avctx, AV_LOG_ERROR, "AVC: nal size %d\n", nalsize); |
8008 | 8032 |
8009 buf_index+=3; | 8033 buf_index+=3; |
8010 } | 8034 } |
8011 | 8035 |
8012 ptr= decode_nal(h, buf + buf_index, &dst_length, &consumed, h->is_avc ? nalsize : buf_size - buf_index); | 8036 ptr= decode_nal(h, buf + buf_index, &dst_length, &consumed, h->is_avc ? nalsize : buf_size - buf_index); |
8037 if (ptr==NULL || dst_length <= 0){ | |
8038 return -1; | |
8039 } | |
8013 while(ptr[dst_length - 1] == 0 && dst_length > 1) | 8040 while(ptr[dst_length - 1] == 0 && dst_length > 1) |
8014 dst_length--; | 8041 dst_length--; |
8015 bit_length= 8*dst_length - decode_rbsp_trailing(ptr + dst_length - 1); | 8042 bit_length= 8*dst_length - decode_rbsp_trailing(ptr + dst_length - 1); |
8016 | 8043 |
8017 if(s->avctx->debug&FF_DEBUG_STARTCODE){ | 8044 if(s->avctx->debug&FF_DEBUG_STARTCODE){ |