/* also responsible for range checking */ int mapping_info_unpack(vorbis_info_mapping *info,vorbis_info *vi, oggpack_buffer *opb){ int i; codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; memset(info,0,sizeof(*info)); if(oggpack_read(opb,1)) info->submaps=oggpack_read(opb,4)+1; else info->submaps=1; if(oggpack_read(opb,1)){ info->coupling_steps=oggpack_read(opb,8)+1; info->coupling= _ogg_malloc(info->coupling_steps*sizeof(*info->coupling)); for(i=0;i<info->coupling_steps;i++){ int testM=info->coupling[i].mag=oggpack_read(opb,ilog(vi->channels)); int testA=info->coupling[i].ang=oggpack_read(opb,ilog(vi->channels)); if(testM<0 || testA<0 || testM==testA || testM>=vi->channels || testA>=vi->channels) goto err_out; } } if(oggpack_read(opb,2)>0)goto err_out; /* 2,3:reserved */ if(info->submaps>1){ info->chmuxlist=_ogg_malloc(sizeof(*info->chmuxlist)*vi->channels); for(i=0;i<vi->channels;i++){ info->chmuxlist[i]=oggpack_read(opb,4); if(info->chmuxlist[i]>=info->submaps)goto err_out; } } info->submaplist=_ogg_malloc(sizeof(*info->submaplist)*info->submaps); for(i=0;i<info->submaps;i++){ int temp=oggpack_read(opb,8); info->submaplist[i].floor=oggpack_read(opb,8); if(info->submaplist[i].floor>=ci->floors)goto err_out; info->submaplist[i].residue=oggpack_read(opb,8); if(info->submaplist[i].residue>=ci->residues)goto err_out; } return 0; err_out: mapping_clear_info(info); return -1; }
void vorbis_info_clear(vorbis_info *vi){ codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; int i; if(ci){ if(ci->mode_param)_ogg_free(ci->mode_param); if(ci->map_param){ for(i=0;i<ci->maps;i++) /* unpack does the range checking */ mapping_clear_info(ci->map_param+i); _ogg_free(ci->map_param); } if(ci->floor_param){ for(i=0;i<ci->floors;i++) /* unpack does the range checking */ if(ci->floor_type[i]) floor1_free_info(ci->floor_param[i]); else floor0_free_info(ci->floor_param[i]); _ogg_free(ci->floor_param); _ogg_free(ci->floor_type); } if(ci->residue_param){ for(i=0;i<ci->residues;i++) /* unpack does the range checking */ res_clear_info(ci->residue_param+i); _ogg_free(ci->residue_param); } if(ci->book_param){ for(i=0;i<ci->books;i++) vorbis_book_clear(ci->book_param+i); _ogg_free(ci->book_param); } _ogg_free(ci); } memset(vi,0,sizeof(*vi)); }