Specwriting found a possible stack smash in floor0.c decode. repaired
[platform/upstream/libvorbis.git] / lib / floor0.c
1 /********************************************************************
2  *                                                                  *
3  * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
5  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
7  *                                                                  *
8  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002             *
9  * by the XIPHOPHORUS Company http://www.xiph.org/                  *
10  *                                                                  *
11  ********************************************************************
12
13  function: floor backend 0 implementation
14  last mod: $Id: floor0.c,v 1.53 2002/07/17 21:34:31 xiphmont Exp $
15
16  ********************************************************************/
17
18 #include <stdlib.h>
19 #include <string.h>
20 #include <math.h>
21 #include <ogg/ogg.h>
22 #include "vorbis/codec.h"
23 #include "codec_internal.h"
24 #include "registry.h"
25 #include "lpc.h"
26 #include "lsp.h"
27 #include "codebook.h"
28 #include "scales.h"
29 #include "misc.h"
30 #include "os.h"
31
32 #include "misc.h"
33 #include <stdio.h>
34
35 typedef struct {
36   int ln;
37   int  m;
38   int **linearmap;
39   int  n[2];
40
41   vorbis_info_floor0 *vi;
42   lpc_lookup lpclook;
43   float *lsp_look;
44
45   long bits;
46   long frames;
47 } vorbis_look_floor0;
48
49
50 /***********************************************/
51
52 static void floor0_free_info(vorbis_info_floor *i){
53   vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
54   if(info){
55     memset(info,0,sizeof(*info));
56     _ogg_free(info);
57   }
58 }
59
60 static void floor0_free_look(vorbis_look_floor *i){
61   vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
62   if(look){
63
64     if(look->linearmap){
65
66       if(look->linearmap[0])_ogg_free(look->linearmap[0]);
67       if(look->linearmap[1])_ogg_free(look->linearmap[1]);
68
69       _ogg_free(look->linearmap);
70     }
71     if(look->lsp_look)_ogg_free(look->lsp_look);
72     lpc_clear(&look->lpclook);
73     memset(look,0,sizeof(*look));
74     _ogg_free(look);
75   }
76 }
77
78 static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
79   codec_setup_info     *ci=vi->codec_setup;
80   int j;
81
82   vorbis_info_floor0 *info=_ogg_malloc(sizeof(*info));
83   info->order=oggpack_read(opb,8);
84   info->rate=oggpack_read(opb,16);
85   info->barkmap=oggpack_read(opb,16);
86   info->ampbits=oggpack_read(opb,6);
87   info->ampdB=oggpack_read(opb,8);
88   info->numbooks=oggpack_read(opb,4)+1;
89   
90   if(info->order<1)goto err_out;
91   if(info->rate<1)goto err_out;
92   if(info->barkmap<1)goto err_out;
93   if(info->numbooks<1)goto err_out;
94     
95   for(j=0;j<info->numbooks;j++){
96     info->books[j]=oggpack_read(opb,8);
97     if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out;
98   }
99   return(info);
100
101  err_out:
102   floor0_free_info(info);
103   return(NULL);
104 }
105
106 /* initialize Bark scale and normalization lookups.  We could do this
107    with static tables, but Vorbis allows a number of possible
108    combinations, so it's best to do it computationally.
109
110    The below is authoritative in terms of defining scale mapping.
111    Note that the scale depends on the sampling rate as well as the
112    linear block and mapping sizes */
113
114 static void floor0_map_lazy_init(vorbis_block      *vb,
115                                  vorbis_info_floor *infoX,
116                                  vorbis_look_floor0 *look){
117   if(!look->linearmap[vb->W]){
118     vorbis_dsp_state   *vd=vb->vd;
119     vorbis_info        *vi=vd->vi;
120     codec_setup_info   *ci=vi->codec_setup;
121     vorbis_info_floor0 *info=(vorbis_info_floor0 *)infoX;
122     int W=vb->W;
123     int n=ci->blocksizes[W]/2,j;
124
125     /* we choose a scaling constant so that:
126        floor(bark(rate/2-1)*C)=mapped-1
127      floor(bark(rate/2)*C)=mapped */
128     float scale=look->ln/toBARK(info->rate/2.f);
129     
130     /* the mapping from a linear scale to a smaller bark scale is
131        straightforward.  We do *not* make sure that the linear mapping
132        does not skip bark-scale bins; the decoder simply skips them and
133        the encoder may do what it wishes in filling them.  They're
134        necessary in some mapping combinations to keep the scale spacing
135        accurate */
136     look->linearmap[W]=_ogg_malloc((n+1)*sizeof(**look->linearmap));
137     for(j=0;j<n;j++){
138       int val=floor( toBARK((info->rate/2.f)/n*j) 
139                      *scale); /* bark numbers represent band edges */
140       if(val>=look->ln)val=look->ln-1; /* guard against the approximation */
141       look->linearmap[W][j]=val;
142     }
143     look->linearmap[W][j]=-1;
144     look->n[W]=n;
145   }
146 }
147
148 static vorbis_look_floor *floor0_look(vorbis_dsp_state *vd,
149                                       vorbis_info_floor *i){
150   int j;
151   vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
152   vorbis_look_floor0 *look=_ogg_calloc(1,sizeof(*look));
153   look->m=info->order;
154   look->ln=info->barkmap;
155   look->vi=info;
156
157   if(vd->analysisp)
158     lpc_init(&look->lpclook,look->ln,look->m);
159
160   look->linearmap=_ogg_calloc(2,sizeof(*look->linearmap));
161
162   look->lsp_look=_ogg_malloc(look->ln*sizeof(*look->lsp_look));
163   for(j=0;j<look->ln;j++)
164     look->lsp_look[j]=2*cos(M_PI/look->ln*j);
165
166   return look;
167 }
168
169 static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
170   vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
171   vorbis_info_floor0 *info=look->vi;
172   int j,k;
173
174   int ampraw=oggpack_read(&vb->opb,info->ampbits);
175   if(ampraw>0){ /* also handles the -1 out of data case */
176     long maxval=(1<<info->ampbits)-1;
177     float amp=(float)ampraw/maxval*info->ampdB;
178     int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks));
179     
180     if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
181       codec_setup_info  *ci=vb->vd->vi->codec_setup;
182       codebook *b=ci->fullbooks+info->books[booknum];
183       float last=0.f;
184
185       /* the additional b->dim is a guard against any possible stack
186          smash; b->dim is provably more than we can overflow the
187          vector */
188       float *lsp=_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1));
189             
190       for(j=0;j<look->m;j+=b->dim)
191         if(vorbis_book_decodev_set(b,lsp+j,&vb->opb,b->dim)==-1)goto eop;
192       for(j=0;j<look->m;){
193         for(k=0;k<b->dim;k++,j++)lsp[j]+=last;
194         last=lsp[j-1];
195       }
196       
197       lsp[look->m]=amp;
198       return(lsp);
199     }
200   }
201  eop:
202   return(NULL);
203 }
204
205 static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
206                            void *memo,float *out){
207   vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
208   vorbis_info_floor0 *info=look->vi;
209   
210   floor0_map_lazy_init(vb,info,look);
211
212   if(memo){
213     float *lsp=(float *)memo;
214     float amp=lsp[look->m];
215
216     /* take the coefficients back to a spectral envelope curve */
217     vorbis_lsp_to_curve(out,
218                         look->linearmap[vb->W],
219                         look->n[vb->W],
220                         look->ln,
221                         lsp,look->m,amp,(float)info->ampdB);
222     return(1);
223   }
224   memset(out,0,sizeof(*out)*look->n[vb->W]);
225   return(0);
226 }
227
228 /* export hooks */
229 vorbis_func_floor floor0_exportbundle={
230   NULL,&floor0_unpack,&floor0_look,&floor0_free_info,
231   &floor0_free_look,&floor0_inverse1,&floor0_inverse2
232 };
233
234
235