Fix out of bounds access in codebook processing
Bug: 62800140
Test: ran poc, CTS
Change-Id: I9960d507be62ee0a3b0aa991240951d5a0784f37
(cherry picked from commit 2c4c4bd895f01fdecb90ebdd0412b60608a9ccf0)
diff --git a/Tremolo/codebook.c b/Tremolo/codebook.c
index 4d0dd91..467640d 100644
--- a/Tremolo/codebook.c
+++ b/Tremolo/codebook.c
@@ -59,7 +59,7 @@
}
static ogg_uint32_t decpack(long entry,long used_entry,long quantvals,
- codebook *b,oggpack_buffer *opb,int maptype){
+ codebook *b,oggpack_buffer *opb,int maptype){
ogg_uint32_t ret=0;
int j;
@@ -72,13 +72,13 @@
if(maptype==1){
/* vals are already read into temporary column vector here */
for(j=0;j<b->dim;j++){
- ogg_uint32_t off=entry%quantvals;
- entry/=quantvals;
- ret|=((ogg_uint16_t *)(b->q_val))[off]<<(b->q_bits*j);
+ ogg_uint32_t off=entry%quantvals;
+ entry/=quantvals;
+ ret|=((ogg_uint16_t *)(b->q_val))[off]<<(b->q_bits*j);
}
}else{
for(j=0;j<b->dim;j++)
- ret|=oggpack_read(opb,b->q_bits)<<(b->q_bits*j);
+ ret|=oggpack_read(opb,b->q_bits)<<(b->q_bits*j);
}
return ret;
@@ -144,7 +144,7 @@
/* given a list of word lengths, number of used entries, and byte
width of a leaf, generate the decode table */
static int _make_words(char *l,long n,ogg_uint32_t *r,long quantvals,
- codebook *b, oggpack_buffer *opb,int maptype){
+ codebook *b, oggpack_buffer *opb,int maptype){
long i,j,count=0;
long top=0;
ogg_uint32_t marker[MARKER_SIZE];
@@ -164,54 +164,54 @@
ALOGE("b/23881715");
return 1;
}
- ogg_uint32_t entry=marker[length];
- long chase=0;
- if(count && !entry)return -1; /* overpopulated tree! */
+ ogg_uint32_t entry=marker[length];
+ long chase=0;
+ if(count && !entry)return -1; /* overpopulated tree! */
- /* chase the tree as far as it's already populated, fill in past */
- for(j=0;j<length-1;j++){
- int bit=(entry>>(length-j-1))&1;
- if(chase>=top){
- if (chase < 0 || chase >= n) return 1;
- top++;
- r[chase*2]=top;
- r[chase*2+1]=0;
- }else
- if (chase < 0 || chase >= n || chase*2+bit > n*2+1) return 1;
- if(!r[chase*2+bit])
- r[chase*2+bit]=top;
- chase=r[chase*2+bit];
- if (chase < 0 || chase >= n) return 1;
- }
- {
- int bit=(entry>>(length-j-1))&1;
- if(chase>=top){
- top++;
- r[chase*2+1]=0;
- }
- r[chase*2+bit]= decpack(i,count++,quantvals,b,opb,maptype) |
- 0x80000000;
- }
+ /* chase the tree as far as it's already populated, fill in past */
+ for(j=0;j<length-1;j++){
+ int bit=(entry>>(length-j-1))&1;
+ if(chase>=top){
+ if (chase < 0 || chase >= n) return 1;
+ top++;
+ r[chase*2]=top;
+ r[chase*2+1]=0;
+ }else
+ if (chase < 0 || chase >= n || chase*2+bit > n*2+1) return 1;
+ if(!r[chase*2+bit])
+ r[chase*2+bit]=top;
+ chase=r[chase*2+bit];
+ if (chase < 0 || chase >= n) return 1;
+ }
+ {
+ int bit=(entry>>(length-j-1))&1;
+ if(chase>=top){
+ top++;
+ r[chase*2+1]=0;
+ }
+ r[chase*2+bit]= decpack(i,count++,quantvals,b,opb,maptype) |
+ 0x80000000;
+ }
- /* Look to see if the next shorter marker points to the node
- above. if so, update it and repeat. */
- for(j=length;j>0;j--){
- if(marker[j]&1){
- marker[j]=marker[j-1]<<1;
- break;
- }
- marker[j]++;
- }
+ /* Look to see if the next shorter marker points to the node
+ above. if so, update it and repeat. */
+ for(j=length;j>0;j--){
+ if(marker[j]&1){
+ marker[j]=marker[j-1]<<1;
+ break;
+ }
+ marker[j]++;
+ }
- /* prune the tree; the implicit invariant says all the longer
- markers were dangling from our just-taken node. Dangle them
- from our *new* node. */
- for(j=length+1;j<MARKER_SIZE;j++)
- if((marker[j]>>1) == entry){
- entry=marker[j];
- marker[j]=marker[j-1]<<1;
- }else
- break;
+ /* prune the tree; the implicit invariant says all the longer
+ markers were dangling from our just-taken node. Dangle them
+ from our *new* node. */
+ for(j=length+1;j<MARKER_SIZE;j++)
+ if((marker[j]>>1) == entry){
+ entry=marker[j];
+ marker[j]=marker[j-1]<<1;
+ }else
+ break;
}
}
}
@@ -234,7 +234,7 @@
}
static int _make_decode_table(codebook *s,char *lengthlist,long quantvals,
- oggpack_buffer *opb,int maptype){
+ oggpack_buffer *opb,int maptype){
int i;
ogg_uint32_t *work;
@@ -251,7 +251,7 @@
/* +1 (rather than -2) is to accommodate 0 and 1 sized books,
which are specialcased to nodeb==4 */
if(_make_words(lengthlist,s->entries,
- s->dec_table,quantvals,s,opb,maptype))return 1;
+ s->dec_table,quantvals,s,opb,maptype))return 1;
return 0;
}
@@ -265,20 +265,20 @@
if (s->used_entries > INT_MAX/(s->dec_leafw+1)) goto error_out;
if (s->dec_nodeb && s->used_entries * (s->dec_leafw+1) > INT_MAX/s->dec_nodeb) goto error_out;
s->dec_table=_ogg_malloc((s->used_entries*(s->dec_leafw+1)-2)*
- s->dec_nodeb);
+ s->dec_nodeb);
if (!s->dec_table) goto error_out;
if(s->dec_leafw==1){
switch(s->dec_nodeb){
case 1:
for(i=0;i<s->used_entries*2-2;i++)
- ((unsigned char *)s->dec_table)[i]=(unsigned char)
- (((work[i] & 0x80000000UL) >> 24) | work[i]);
+ ((unsigned char *)s->dec_table)[i]=(unsigned char)
+ (((work[i] & 0x80000000UL) >> 24) | work[i]);
break;
case 2:
for(i=0;i<s->used_entries*2-2;i++)
- ((ogg_uint16_t *)s->dec_table)[i]=(ogg_uint16_t)
- (((work[i] & 0x80000000UL) >> 16) | work[i]);
+ ((ogg_uint16_t *)s->dec_table)[i]=(ogg_uint16_t)
+ (((work[i] & 0x80000000UL) >> 16) | work[i]);
break;
}
@@ -290,62 +290,62 @@
unsigned char *out=(unsigned char *)s->dec_table;
for(i=s->used_entries*2-4;i>=0;i-=2){
- if(work[i]&0x80000000UL){
- if(work[i+1]&0x80000000UL){
- top-=4;
- out[top]=(work[i]>>8 & 0x7f)|0x80;
- out[top+1]=(work[i+1]>>8 & 0x7f)|0x80;
- out[top+2]=work[i] & 0xff;
- out[top+3]=work[i+1] & 0xff;
- }else{
- top-=3;
- out[top]=(work[i]>>8 & 0x7f)|0x80;
- out[top+1]=work[work[i+1]*2];
- out[top+2]=work[i] & 0xff;
- }
- }else{
- if(work[i+1]&0x80000000UL){
- top-=3;
- out[top]=work[work[i]*2];
- out[top+1]=(work[i+1]>>8 & 0x7f)|0x80;
- out[top+2]=work[i+1] & 0xff;
- }else{
- top-=2;
- out[top]=work[work[i]*2];
- out[top+1]=work[work[i+1]*2];
- }
- }
- work[i]=top;
+ if(work[i]&0x80000000UL){
+ if(work[i+1]&0x80000000UL){
+ top-=4;
+ out[top]=(work[i]>>8 & 0x7f)|0x80;
+ out[top+1]=(work[i+1]>>8 & 0x7f)|0x80;
+ out[top+2]=work[i] & 0xff;
+ out[top+3]=work[i+1] & 0xff;
+ }else{
+ top-=3;
+ out[top]=(work[i]>>8 & 0x7f)|0x80;
+ out[top+1]=work[work[i+1]*2];
+ out[top+2]=work[i] & 0xff;
+ }
+ }else{
+ if(work[i+1]&0x80000000UL){
+ top-=3;
+ out[top]=work[work[i]*2];
+ out[top+1]=(work[i+1]>>8 & 0x7f)|0x80;
+ out[top+2]=work[i+1] & 0xff;
+ }else{
+ top-=2;
+ out[top]=work[work[i]*2];
+ out[top+1]=work[work[i+1]*2];
+ }
+ }
+ work[i]=top;
}
}else{
ogg_uint16_t *out=(ogg_uint16_t *)s->dec_table;
for(i=s->used_entries*2-4;i>=0;i-=2){
- if(work[i]&0x80000000UL){
- if(work[i+1]&0x80000000UL){
- top-=4;
- out[top]=(work[i]>>16 & 0x7fff)|0x8000;
- out[top+1]=(work[i+1]>>16 & 0x7fff)|0x8000;
- out[top+2]=work[i] & 0xffff;
- out[top+3]=work[i+1] & 0xffff;
- }else{
- top-=3;
- out[top]=(work[i]>>16 & 0x7fff)|0x8000;
- out[top+1]=work[work[i+1]*2];
- out[top+2]=work[i] & 0xffff;
- }
- }else{
- if(work[i+1]&0x80000000UL){
- top-=3;
- out[top]=work[work[i]*2];
- out[top+1]=(work[i+1]>>16 & 0x7fff)|0x8000;
- out[top+2]=work[i+1] & 0xffff;
- }else{
- top-=2;
- out[top]=work[work[i]*2];
- out[top+1]=work[work[i+1]*2];
- }
- }
- work[i]=top;
+ if(work[i]&0x80000000UL){
+ if(work[i+1]&0x80000000UL){
+ top-=4;
+ out[top]=(work[i]>>16 & 0x7fff)|0x8000;
+ out[top+1]=(work[i+1]>>16 & 0x7fff)|0x8000;
+ out[top+2]=work[i] & 0xffff;
+ out[top+3]=work[i+1] & 0xffff;
+ }else{
+ top-=3;
+ out[top]=(work[i]>>16 & 0x7fff)|0x8000;
+ out[top+1]=work[work[i+1]*2];
+ out[top+2]=work[i] & 0xffff;
+ }
+ }else{
+ if(work[i+1]&0x80000000UL){
+ top-=3;
+ out[top]=work[work[i]*2];
+ out[top+1]=(work[i+1]>>16 & 0x7fff)|0x8000;
+ out[top+2]=work[i+1] & 0xffff;
+ }else{
+ top-=2;
+ out[top]=work[work[i]*2];
+ out[top+1]=work[work[i+1]*2];
+ }
+ }
+ work[i]=top;
}
}
}
@@ -436,23 +436,23 @@
/* yes, unused entries */
for(i=0;i<s->entries;i++){
- if(oggpack_read(opb,1)){
- long num=oggpack_read(opb,5);
- if(num==-1)goto _eofout;
- lengthlist[i]=(char)(num+1);
- s->used_entries++;
- if(num+1>s->dec_maxlength)s->dec_maxlength=num+1;
- }else
- lengthlist[i]=0;
+ if(oggpack_read(opb,1)){
+ long num=oggpack_read(opb,5);
+ if(num==-1)goto _eofout;
+ lengthlist[i]=(char)(num+1);
+ s->used_entries++;
+ if(num+1>s->dec_maxlength)s->dec_maxlength=num+1;
+ }else
+ lengthlist[i]=0;
}
}else{
/* all entries used; no tagging */
s->used_entries=s->entries;
for(i=0;i<s->entries;i++){
- long num=oggpack_read(opb,5);
- if(num==-1)goto _eofout;
- lengthlist[i]=(char)(num+1);
- if(num+1>s->dec_maxlength)s->dec_maxlength=num+1;
+ long num=oggpack_read(opb,5);
+ if(num==-1)goto _eofout;
+ lengthlist[i]=(char)(num+1);
+ if(num+1>s->dec_maxlength)s->dec_maxlength=num+1;
}
}
@@ -467,12 +467,12 @@
if (!lengthlist) goto _eofout;
for(i=0;i<s->entries;){
- long num=oggpack_read(opb,_ilog(s->entries-i));
- if(num<0)goto _eofout;
- for(j=0;j<num && i<s->entries;j++,i++)
- lengthlist[i]=(char)length;
- s->dec_maxlength=length;
- length++;
+ long num=oggpack_read(opb,_ilog(s->entries-i));
+ if(num<0)goto _eofout;
+ for(j=0;j<num && i<s->entries;j++,i++)
+ lengthlist[i]=(char)length;
+ s->dec_maxlength=length;
+ length++;
}
}
break;
@@ -524,55 +524,55 @@
if(total1<=4 && total1<=total2){
- /* use dec_type 1: vector of packed values */
+ /* use dec_type 1: vector of packed values */
- /* need quantized values before */
- s->q_val=calloc(sizeof(ogg_uint16_t), quantvals);
- if (!s->q_val) goto _eofout;
- for(i=0;i<quantvals;i++)
- ((ogg_uint16_t *)s->q_val)[i]=(ogg_uint16_t)oggpack_read(opb,s->q_bits);
+ /* need quantized values before */
+ s->q_val=calloc(sizeof(ogg_uint16_t), quantvals);
+ if (!s->q_val) goto _eofout;
+ for(i=0;i<quantvals;i++)
+ ((ogg_uint16_t *)s->q_val)[i]=(ogg_uint16_t)oggpack_read(opb,s->q_bits);
- if(oggpack_eop(opb)){
- goto _eofout;
- }
+ if(oggpack_eop(opb)){
+ goto _eofout;
+ }
- s->dec_type=1;
- s->dec_nodeb=_determine_node_bytes(s->used_entries,
- (s->q_bits*s->dim+8)/8);
- s->dec_leafw=_determine_leaf_words(s->dec_nodeb,
- (s->q_bits*s->dim+8)/8);
- if(_make_decode_table(s,lengthlist,quantvals,opb,maptype)){
- goto _errout;
- }
+ s->dec_type=1;
+ s->dec_nodeb=_determine_node_bytes(s->used_entries,
+ (s->q_bits*s->dim+8)/8);
+ s->dec_leafw=_determine_leaf_words(s->dec_nodeb,
+ (s->q_bits*s->dim+8)/8);
+ if(_make_decode_table(s,lengthlist,quantvals,opb,maptype)){
+ goto _errout;
+ }
- free(s->q_val);
- s->q_val=0;
+ free(s->q_val);
+ s->q_val=0;
}else{
- /* use dec_type 2: packed vector of column offsets */
+ /* use dec_type 2: packed vector of column offsets */
- /* need quantized values before */
- if(s->q_bits<=8){
- s->q_val=_ogg_malloc(quantvals);
- if (!s->q_val) goto _eofout;
- for(i=0;i<quantvals;i++)
- ((unsigned char *)s->q_val)[i]=(unsigned char)oggpack_read(opb,s->q_bits);
- }else{
- s->q_val=_ogg_malloc(quantvals*2);
- if (!s->q_val) goto _eofout;
- for(i=0;i<quantvals;i++)
- ((ogg_uint16_t *)s->q_val)[i]=(ogg_uint16_t)oggpack_read(opb,s->q_bits);
- }
+ /* need quantized values before */
+ if(s->q_bits<=8){
+ s->q_val=_ogg_malloc(quantvals);
+ if (!s->q_val) goto _eofout;
+ for(i=0;i<quantvals;i++)
+ ((unsigned char *)s->q_val)[i]=(unsigned char)oggpack_read(opb,s->q_bits);
+ }else{
+ s->q_val=_ogg_malloc(quantvals*2);
+ if (!s->q_val) goto _eofout;
+ for(i=0;i<quantvals;i++)
+ ((ogg_uint16_t *)s->q_val)[i]=(ogg_uint16_t)oggpack_read(opb,s->q_bits);
+ }
- if(oggpack_eop(opb))goto _eofout;
+ if(oggpack_eop(opb))goto _eofout;
- s->q_pack=_ilog(quantvals-1);
- s->dec_type=2;
- s->dec_nodeb=_determine_node_bytes(s->used_entries,
- (_ilog(quantvals-1)*s->dim+8)/8);
- s->dec_leafw=_determine_leaf_words(s->dec_nodeb,
- (_ilog(quantvals-1)*s->dim+8)/8);
- if(_make_decode_table(s,lengthlist,quantvals,opb,maptype))goto _errout;
+ s->q_pack=_ilog(quantvals-1);
+ s->dec_type=2;
+ s->dec_nodeb=_determine_node_bytes(s->used_entries,
+ (_ilog(quantvals-1)*s->dim+8)/8);
+ s->dec_leafw=_determine_leaf_words(s->dec_nodeb,
+ (_ilog(quantvals-1)*s->dim+8)/8);
+ if(_make_decode_table(s,lengthlist,quantvals,opb,maptype))goto _errout;
}
}
@@ -604,11 +604,11 @@
s->q_val=_ogg_malloc(s->q_pack*s->used_entries);
if(s->q_bits<=8){
- for(i=0;i<s->used_entries*s->dim;i++)
- ((unsigned char *)(s->q_val))[i]=(unsigned char)oggpack_read(opb,s->q_bits);
+ for(i=0;i<s->used_entries*s->dim;i++)
+ ((unsigned char *)(s->q_val))[i]=(unsigned char)oggpack_read(opb,s->q_bits);
}else{
- for(i=0;i<s->used_entries*s->dim;i++)
- ((ogg_uint16_t *)(s->q_val))[i]=(ogg_uint16_t)oggpack_read(opb,s->q_bits);
+ for(i=0;i<s->used_entries*s->dim;i++)
+ ((ogg_uint16_t *)(s->q_val))[i]=(ogg_uint16_t)oggpack_read(opb,s->q_bits);
}
}
break;
@@ -646,7 +646,7 @@
oggpack_buffer *b);
#else
static inline ogg_uint32_t decode_packed_entry_number(codebook *book,
- oggpack_buffer *b){
+ oggpack_buffer *b){
ogg_uint32_t chase=0;
int read=book->dec_maxlength;
long lok = oggpack_look(b,read),i;
@@ -669,8 +669,8 @@
unsigned char *t=(unsigned char *)book->dec_table;
for(i=0;i<read;i++){
- chase=t[chase*2+((lok>>i)&1)];
- if(chase&0x80UL)break;
+ chase=t[chase*2+((lok>>i)&1)];
+ if(chase&0x80UL)break;
}
chase&=0x7fUL;
break;
@@ -681,13 +681,13 @@
/* 8/16 - Used by infile2 */
unsigned char *t=(unsigned char *)book->dec_table;
for(i=0;i<read;i++){
- int bit=(lok>>i)&1;
- int next=t[chase+bit];
- if(next&0x80){
- chase= (next<<8) | t[chase+bit+1+(!bit || t[chase]&0x80)];
- break;
- }
- chase=next;
+ int bit=(lok>>i)&1;
+ int next=t[chase+bit];
+ if(next&0x80){
+ chase= (next<<8) | t[chase+bit+1+(!bit || t[chase]&0x80)];
+ break;
+ }
+ chase=next;
}
//chase&=0x7fffUL;
chase&=~0x8000UL;
@@ -698,8 +698,8 @@
/* book->dec_nodeb==2, book->dec_leafw==1 */
/* 16/16 - Used */
for(i=0;i<read;i++){
- chase=((ogg_uint16_t *)(book->dec_table))[chase*2+((lok>>i)&1)];
- if(chase&0x8000UL)break;
+ chase=((ogg_uint16_t *)(book->dec_table))[chase*2+((lok>>i)&1)];
+ if(chase&0x8000UL)break;
}
//chase&=0x7fffUL;
chase&=~0x8000UL;
@@ -711,13 +711,13 @@
/* 16/32 - Used by infile2 */
ogg_uint16_t *t=(ogg_uint16_t *)book->dec_table;
for(i=0;i<read;i++){
- int bit=(lok>>i)&1;
- int next=t[chase+bit];
- if(next&0x8000){
- chase= (next<<16) | t[chase+bit+1+(!bit || t[chase]&0x8000)];
- break;
- }
- chase=next;
+ int bit=(lok>>i)&1;
+ int next=t[chase+bit];
+ if(next&0x8000){
+ chase= (next<<16) | t[chase+bit+1+(!bit || t[chase]&0x8000)];
+ break;
+ }
+ chase=next;
}
//chase&=0x7fffffffUL;
chase&=~0x80000000UL;
@@ -727,8 +727,8 @@
{
//Output("32/32");
for(i=0;i<read;i++){
- chase=((ogg_uint32_t *)(book->dec_table))[chase*2+((lok>>i)&1)];
- if(chase&0x80000000UL)break;
+ chase=((ogg_uint32_t *)(book->dec_table))[chase*2+((lok>>i)&1)];
+ if(chase&0x80000000UL)break;
}
//chase&=0x7fffffffUL;
chase&=~0x80000000UL;
@@ -777,9 +777,9 @@
int mask=(1<<s->q_pack)-1;
for(i=0;i<s->dim;i++){
if(s->q_bits<=8)
- v[i]=((unsigned char *)(s->q_val))[entry&mask];
+ v[i]=((unsigned char *)(s->q_val))[entry&mask];
else
- v[i]=((ogg_uint16_t *)(s->q_val))[entry&mask];
+ v[i]=((ogg_uint16_t *)(s->q_val))[entry&mask];
entry>>=s->q_pack;
}
break;
@@ -790,10 +790,10 @@
if(s->q_bits<=8){
for(i=0;i<s->dim;i++)
- v[i]=((unsigned char *)ptr)[i];
+ v[i]=((unsigned char *)ptr)[i];
}else{
for(i=0;i<s->dim;i++)
- v[i]=((ogg_uint16_t *)ptr)[i];
+ v[i]=((ogg_uint16_t *)ptr)[i];
}
break;
}
@@ -823,7 +823,7 @@
if(s->q_seq)
for(i=1;i<s->dim;i++)
- v[i]+=v[i-1];
+ v[i]+=v[i-1];
}
return 0;
@@ -832,7 +832,7 @@
/* returns 0 on OK or -1 on eof *************************************/
long vorbis_book_decodevs_add(codebook *book,ogg_int32_t *a,
- oggpack_buffer *b,int n,int point){
+ oggpack_buffer *b,int n,int point){
if(book->used_entries>0){
int step=n/book->dim;
ogg_int32_t *v = book->dec_buf;//(ogg_int32_t *)alloca(sizeof(*v)*book->dim);
@@ -842,14 +842,14 @@
for (j=0;j<step;j++){
if(decode_map(book,b,v,point))return -1;
for(i=0,o=j;i<book->dim;i++,o+=step)
- a[o]+=v[i];
+ a[o]+=v[i];
}
}
return 0;
}
long vorbis_book_decodev_add(codebook *book,ogg_int32_t *a,
- oggpack_buffer *b,int n,int point){
+ oggpack_buffer *b,int n,int point){
if(book->used_entries>0){
ogg_int32_t *v = book->dec_buf;//(ogg_int32_t *)alloca(sizeof(*v)*book->dim);
int i,j;
@@ -857,15 +857,15 @@
if (!v) return -1;
for(i=0;i<n;){
if(decode_map(book,b,v,point))return -1;
- for (j=0;j<book->dim;j++)
- a[i++]+=v[j];
+ for (j=0;j<book->dim && i < n;j++)
+ a[i++]+=v[j];
}
}
return 0;
}
long vorbis_book_decodev_set(codebook *book,ogg_int32_t *a,
- oggpack_buffer *b,int n,int point){
+ oggpack_buffer *b,int n,int point){
if(book->used_entries>0){
ogg_int32_t *v = book->dec_buf;//(ogg_int32_t *)alloca(sizeof(*v)*book->dim);
int i,j;
@@ -873,15 +873,15 @@
if (!v) return -1;
for(i=0;i<n;){
if(decode_map(book,b,v,point))return -1;
- for (j=0;j<book->dim;j++)
- a[i++]=v[j];
+ for (j=0;j<book->dim && i < n;j++)
+ a[i++]=v[j];
}
}else{
int i,j;
for(i=0;i<n;){
- for (j=0;j<book->dim;j++)
- a[i++]=0;
+ for (j=0;j<book->dim && i < n;j++)
+ a[i++]=0;
}
}
@@ -890,12 +890,12 @@
#ifndef ONLY_C
long vorbis_book_decodevv_add(codebook *book,ogg_int32_t **a,
- long offset,int ch,
- oggpack_buffer *b,int n,int point);
+ long offset,int ch,
+ oggpack_buffer *b,int n,int point);
#else
long vorbis_book_decodevv_add(codebook *book,ogg_int32_t **a,
- long offset,int ch,
- oggpack_buffer *b,int n,int point){
+ long offset,int ch,
+ oggpack_buffer *b,int n,int point){
if(book->used_entries>0){
ogg_int32_t *v = book->dec_buf;//(ogg_int32_t *)alloca(sizeof(*v)*book->dim);
@@ -905,12 +905,12 @@
if (!v) return -1;
for(i=offset;i<offset+n;){
if(decode_map(book,b,v,point))return -1;
- for (j=0;j<book->dim;j++){
- a[chptr++][i]+=v[j];
- if(chptr==ch){
- chptr=0;
- i++;
- }
+ for (j=0;j<book->dim && i < offset + n;j++){
+ a[chptr++][i]+=v[j];
+ if(chptr==ch){
+ chptr=0;
+ i++;
+ }
}
}
}
diff --git a/Tremolo/dpen.s b/Tremolo/dpen.s
index 7e4f1ed..344e41b 100644
--- a/Tremolo/dpen.s
+++ b/Tremolo/dpen.s
@@ -430,6 +430,8 @@
LDR r0, [r9, # 5*4] @ r0 = book->dim
LDR r1, [r9, #14*4] @ r1 = v = dec_buf
vbdvva_loop2:
+ CMP r5,#0
+ BLE vbdvva_exit
LDR r2, [r10],#4 @ r2 = a[chptr++]
LDR r12,[r1], #4 @ r1 = v[j++]
CMP r10,r8 @ if (chptr == ch)
diff --git a/Tremolo/res012.c b/Tremolo/res012.c
index d6495fb..ac09671 100644
--- a/Tremolo/res012.c
+++ b/Tremolo/res012.c
@@ -65,9 +65,9 @@
if(info->type>2 || info->type<0)goto errout;
info->begin=oggpack_read(opb,24);
info->end=oggpack_read(opb,24);
- info->grouping=oggpack_read(opb,24)+1;
- info->partitions=(char)(oggpack_read(opb,6)+1);
- info->groupbook=(unsigned char)oggpack_read(opb,8);
+ info->grouping=oggpack_read(opb,24)+1; // "partition size" in spec
+ info->partitions=(char)(oggpack_read(opb,6)+1); // "classification" in spec
+ info->groupbook=(unsigned char)oggpack_read(opb,8); // "classbook" in spec
if(info->groupbook>=ci->books)goto errout;
info->stagemasks=_ogg_malloc(info->partitions*sizeof(*info->stagemasks));
@@ -94,6 +94,15 @@
if(oggpack_eop(opb))goto errout;
+ // According to the Vorbis spec (paragraph 8.6.2 "packet decode"), residue
+ // begin and end should be limited to the maximum possible vector size in
+ // case they exceed it. However doing that makes the decoder crash further
+ // down, so we return an error instead.
+ int limit = (info->type == 2 ? vi->channels : 1) * ci->blocksizes[1] / 2;
+ if (info->begin > info->end ||
+ info->end > limit) {
+ goto errout;
+ }
return 0;
errout:
res_clear_info(info);