ref: bc3e181d1f2a0f35f001745e02b28911b3f4035d
parent: f2292afacba3a4eee3566d263cd15cccc950abc0
author: cbagwell <cbagwell>
date: Sun Mar 24 20:31:02 EST 2002
Fixing integer overflow bugs in resample and compand effects.
--- a/Changelog
+++ b/Changelog
@@ -18,6 +18,10 @@
o Updated config.sub to detect latest supported OS's.
o Fabrizio Gennari added support for reading and writing
MP3 files using the external libraries libmad and libmp3lame.
+ o Jens Henrik Goebbert sent in several bugfixes for integer overflows
+ in the compand effect.
+ o Dan Dickerman sent in patches for integer overflows in the resample
+ effect.
sox-12.17.3
-----------
--- a/src/compand.c
+++ b/src/compand.c
@@ -60,6 +60,7 @@
st_ssize_t delay_buf_size;/* Size of delay_buf in samples */
st_ssize_t delay_buf_ptr; /* Index into delay_buf */
st_ssize_t delay_buf_cnt; /* No. of active entries in delay_buf */
+ short int delay_buf_full; /* Shows buffer situation (important for st_compand_drain) */
} *compand_t;
/*
@@ -247,6 +248,7 @@
l->delay_buf[i] = 0;
l->delay_buf_ptr = 0;
l->delay_buf_cnt = 0;
+ l->delay_buf_full= 0;
return (ST_SUCCESS);
}
@@ -258,7 +260,7 @@
static void doVolume(double *v, double samp, compand_t l, int chan)
{
- double s = samp/(~((st_sample_t)1<<31));
+ double s = samp/ST_SAMPLE_MAX;
double delta = s - *v;
if (delta > 0.0) /* increase volume according to attack rate */
@@ -277,9 +279,10 @@
compand_t l = (compand_t) effp->priv;
int len = (*isamp > *osamp) ? *osamp : *isamp;
int filechans = effp->outinfo.channels;
- int done;
+ int idone,odone;
+ int64_t checkbuf; //if st_sample_t of type int32_t
- for (done = 0; done < len; ibuf += filechans) {
+ for (idone = 0,odone = 0; idone < len; ibuf += filechans) {
int chan;
/* Maintain the volume fields by simulating a leaky pump circuit */
@@ -302,7 +305,7 @@
/* Volume memory is updated: perform compand */
for (chan = 0; chan < filechans; ++chan) {
- double v = l->expectedChannels > 1 ?
+ double v = l->expectedChannels > 1 ?
l->volume[chan] : l->volume[0];
double outv;
int piece;
@@ -313,7 +316,7 @@
if (v >= l->transferIns[piece - 1] &&
v < l->transferIns[piece])
break;
-
+
outv = l->transferOuts[piece-1] +
(l->transferOuts[piece] - l->transferOuts[piece-1]) *
(v - l->transferIns[piece-1]) /
@@ -320,12 +323,39 @@
(l->transferIns[piece] - l->transferIns[piece-1]);
if (l->delay_buf_size <= 0)
- obuf[done++] = ibuf[chan]*(outv/v)*l->outgain;
- else {
+ {
+ checkbuf = ibuf[chan]*(outv/v)*l->outgain;
+ if(checkbuf > ST_SAMPLE_MAX)
+ obuf[odone] = ST_SAMPLE_MAX;
+ else if(checkbuf < ST_SAMPLE_MIN)
+ obuf[odone] = ST_SAMPLE_MIN;
+ else
+ obuf[odone] = checkbuf;
+
+ idone++;
+ odone++;
+ }
+ else
+ {
if (l->delay_buf_cnt >= l->delay_buf_size)
- obuf[done++] = l->delay_buf[l->delay_buf_ptr]*(outv/v)*l->outgain;
+ {
+ l->delay_buf_full=1; //delay buffer is now definetly full
+ checkbuf = l->delay_buf[l->delay_buf_ptr]*(outv/v)*l->outgain;
+ if(checkbuf > ST_SAMPLE_MAX)
+ obuf[odone] = ST_SAMPLE_MAX;
+ else if(checkbuf < ST_SAMPLE_MIN)
+ obuf[odone] = ST_SAMPLE_MIN;
+ else
+ obuf[odone] = checkbuf;
+
+ odone++;
+ idone++;
+ }
else
+ {
l->delay_buf_cnt++;
+ idone++; //no "odone++" because we did not fill obuf[...]
+ }
l->delay_buf[l->delay_buf_ptr++] = ibuf[chan];
l->delay_buf_ptr %= l->delay_buf_size;
}
@@ -332,12 +362,12 @@
}
}
- *isamp = done; *osamp = done;
+ *isamp = idone; *osamp = odone;
return (ST_SUCCESS);
}
/*
- * Drain out compander delay lines.
+ * Drain out compander delay lines.
*/
int st_compand_drain(eff_t effp, st_sample_t *obuf, st_size_t *osamp)
{
@@ -347,6 +377,7 @@
/*
* Drain out delay samples. Note that this loop does all channels.
*/
+ if(l->delay_buf_full==0) l->delay_buf_ptr=0;
for (done = 0; done < *osamp && l->delay_buf_cnt > 0; done++) {
obuf[done] = l->delay_buf[l->delay_buf_ptr++];
l->delay_buf_ptr %= l->delay_buf_size;
--- a/src/resample.c
+++ b/src/resample.c
@@ -353,8 +353,18 @@
r->Xread = i;
r->Xp = r->Xoff;
- for(i=0; i < Nout; i++)
- *obuf++ = r->Y[i] * ISCALE;
+ for(i=0; i < Nout; i++) {
+ // orig: *obuf++ = r->Y[i] * ISCALE;
+ Float ftemp = r->Y[i] * ISCALE;
+
+ if (ftemp >= ST_SAMPLE_MAX)
+ *obuf = ST_SAMPLE_MAX;
+ else if (ftemp <= ST_SAMPLE_MIN)
+ *obuf = ST_SAMPLE_MIN;
+ else
+ *obuf = ftemp;
+ obuf++;
+ }
*isamp = Nx;
*osamp = Nout;