1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
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;i<st->nb_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
|