From 5fb866e8f3feae2ca9a0742312c5a6fa41627ef8 Mon Sep 17 00:00:00 2001 From: Monty Date: Sat, 23 Oct 2010 10:34:24 +0000 Subject: [PATCH] Commit tterribe's port of Tremor r17541: Harden the code that trims the last packet of a stream; it was possible to game the granpos such that the trim code would try to rewind more samples than were actually available in storage. Also, fix/eliminate two printf warnings in seeking_example extension. svn path=/trunk/vorbis/; revision=17561 --- examples/seeking_example.c | 4 ++-- lib/block.c | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/examples/seeking_example.c b/examples/seeking_example.c index 6355359..cbd5a9b 100644 --- a/examples/seeking_example.c +++ b/examples/seeking_example.c @@ -61,13 +61,13 @@ void _verify(OggVorbis_File *ov, bread=ov_read(ov,buffer,4096,1,1,1,&dummy); for(j=0;j>hs)*2)]){ - fprintf(stderr,"data after seek doesn't match declared pcm position %lld\n",pos); + fprintf(stderr,"data after seek doesn't match declared pcm position %ld\n",(long)pos); for(i=0;i<(pcmlength>>hs)*2-bread;i++){ for(j=0;jsample_count>v->granulepos){ /* corner case; if this is both the first and last audio page, then spec says the end is cut, not beginning */ + long extra=b->sample_count-vb->granulepos; + + /* we use ogg_int64_t for granule positions because a + uint64 isn't universally available. Unfortunately, + that means granposes can be 'negative' and result in + extra being negative */ + if(extra<0) + extra=0; + if(vb->eofflag){ /* trim the end */ /* no preceding granulepos; assume we started at zero (we'd @@ -867,10 +876,16 @@ int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){ /* granulepos could be -1 due to a seek, but that would result in a long count, not short count */ - v->pcm_current-=(b->sample_count-v->granulepos)>>hs; + /* Guard against corrupt/malicious frames that set EOP and + a backdated granpos; don't rewind more samples than we + actually have */ + if(extra > (v->pcm_current - v->pcm_returned)<pcm_current - v->pcm_returned)<pcm_current-=extra>>hs; }else{ /* trim the beginning */ - v->pcm_returned+=(b->sample_count-v->granulepos)>>hs; + v->pcm_returned+=extra>>hs; if(v->pcm_returned>v->pcm_current) v->pcm_returned=v->pcm_current; } @@ -888,6 +903,20 @@ int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){ if(extra) if(vb->eofflag){ /* partial last frame. Strip the extra samples off */ + + /* Guard against corrupt/malicious frames that set EOP and + a backdated granpos; don't rewind more samples than we + actually have */ + if(extra > (v->pcm_current - v->pcm_returned)<pcm_current - v->pcm_returned)<pcm_current-=extra>>hs; } /* else {Shouldn't happen *unless* the bitstream is out of spec. Either way, believe the bitstream } */ -- 2.7.4