diff --git a/media/libspeex_resampler/fix-overflow.patch b/media/libspeex_resampler/fix-overflow.patch new file mode 100644 index 0000000..e69de29 diff --git a/media/libspeex_resampler/src/resample.c b/media/libspeex_resampler/src/resample.c index a3859e3..d99595a 100644 --- a/media/libspeex_resampler/src/resample.c +++ b/media/libspeex_resampler/src/resample.c @@ -98,6 +98,10 @@ static void speex_free (void *ptr) {free(ptr);} #define NULL 0 #endif +#ifndef UINT32_MAX +#define UINT32_MAX 4294967296U +#endif + #include "simd_detect.h" /* Numer of elements to allocate on the stack */ @@ -603,6 +607,22 @@ static int resampler_basic_zero(SpeexResamplerState *st, spx_uint32_t channel_in return out_sample; } +static int _muldiv_safe(spx_uint32_t value, spx_uint32_t mul, spx_uint32_t div) +{ + /* TODO: Could be simplified with 64 bits operation. */ + spx_uint32_t major = value / div; + spx_uint32_t remainder = value % div; + return remainder <= UINT32_MAX / mul && major <= UINT32_MAX / mul && + major * mul <= UINT32_MAX - remainder * mul / div; +} + +static spx_uint32_t _muldiv(spx_uint32_t value, spx_uint32_t mul, spx_uint32_t div) +{ + spx_uint32_t major = value / div; + spx_uint32_t remainder = value % div; + return remainder * mul / div + major * mul; +} + static int update_filter(SpeexResamplerState *st) { spx_uint32_t old_length = st->filt_len; @@ -620,8 +640,9 @@ static int update_filter(SpeexResamplerState *st) { /* down-sampling */ st->cutoff = quality_map[st->quality].downsample_bandwidth * st->den_rate / st->num_rate; - /* FIXME: divide the numerator and denominator by a certain amount if they're too large */ - st->filt_len = st->filt_len*st->num_rate / st->den_rate; + if (!_muldiv_safe(st->filt_len,st->num_rate,st->den_rate)) + goto fail; + st->filt_len = _muldiv(st->filt_len,st->num_rate,st->den_rate); /* Round up to make sure we have a multiple of 8 for SSE */ st->filt_len = ((st->filt_len-1)&(~0x7))+8; if (2*st->den_rate < st->num_rate) @@ -1129,7 +1150,9 @@ EXPORT int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t r { for (i=0;inb_channels;i++) { - st->samp_frac_num[i]=st->samp_frac_num[i]*st->den_rate/old_den; + if (!_muldiv_safe(st->samp_frac_num[i],st->den_rate,old_den)) + return RESAMPLER_ERR_OVERFLOW; + st->samp_frac_num[i]= _muldiv(st->samp_frac_num[i],st->den_rate,old_den); /* Safety net */ if (st->samp_frac_num[i] >= st->den_rate) st->samp_frac_num[i] = st->den_rate-1; diff --git a/media/libspeex_resampler/src/speex_resampler.h b/media/libspeex_resampler/src/speex_resampler.h index 70abe52..1286872 100644 --- a/media/libspeex_resampler/src/speex_resampler.h +++ b/media/libspeex_resampler/src/speex_resampler.h @@ -106,7 +106,8 @@ enum { RESAMPLER_ERR_BAD_STATE = 2, RESAMPLER_ERR_INVALID_ARG = 3, RESAMPLER_ERR_PTR_OVERLAP = 4, - + RESAMPLER_ERR_OVERFLOW = 5, + RESAMPLER_ERR_MAX_ERROR }; diff --git a/media/libspeex_resampler/update.sh b/media/libspeex_resampler/update.sh index d4a025b..6950bc6 100644 --- a/media/libspeex_resampler/update.sh +++ b/media/libspeex_resampler/update.sh @@ -26,3 +26,4 @@ patch -p3 < set-skip-frac.patch patch -p3 < hugemem.patch patch -p3 < remove-empty-asm-clobber.patch patch -p3 < handle-memory-error.patch +patch -p3 < fix-overflow.patch