summaryrefslogtreecommitdiffstats
path: root/media/libspeex_resampler/fix-overflow.patch
blob: cee9a7edb34e9b2a9857ab018bb174ca088ba4c9 (plain)
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