ref: 29b71dfb1f79038c5934ea466b1e67f202487a46
parent: d4f1dc2eeaabe76405426dae1d79a186259f41ca
author: Erik de Castro Lopo <erikd@mega-nerd.com>
date: Sat Feb 14 16:17:29 EST 2009
Fix a segfault which occurs when memcpy is passed a bad length parameter. Thanks to David Cournapeau for the bug report.
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,13 @@
* src/common.h
Add WARN_UNUSED macro.
+ * src/src_sinc.c
+ Fix a segfault which occurs when memcpy is passed a bad length parameter.
+ This bug has zero security implications beyond the ability to cause a
+ program hitting this bug to exit immediately with a segfault.
+ See : http://www.mega-nerd.com/erikd/Blog/2009/Feb/14/index.html
+ Thanks to David Cournapeau for the bug report.
+
2009-02-13 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
* src/common.h src/samplerate.c
--- a/src/src_sinc.c
+++ b/src/src_sinc.c
@@ -79,7 +79,7 @@
static int sinc_stereo_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
static int sinc_mono_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
-static void prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len) ;
+static int prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len) WARN_UNUSED ;
static void sinc_reset (SRC_PRIVATE *psrc) ;
@@ -226,7 +226,7 @@
** a better way. Need to look at prepare_data () at the same time.
*/
- temp_filter.b_len = 2 * lrint (1.0 + temp_filter.coeff_half_len / (temp_filter.index_inc * 1.0) * SRC_MAX_RATIO) ;
+ temp_filter.b_len = lrint (2.5 * temp_filter.coeff_half_len / (temp_filter.index_inc * 1.0) * SRC_MAX_RATIO) ;
temp_filter.b_len = MAX (temp_filter.b_len, 4096) ;
temp_filter.b_len *= temp_filter.channels ;
@@ -371,7 +371,8 @@
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
if (samples_in_hand <= half_filter_chan_len)
- { prepare_data (filter, data, half_filter_chan_len) ;
+ { if ((psrc->error = prepare_data (filter, data, half_filter_chan_len)) != 0)
+ return psrc->error ;
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
if (samples_in_hand <= half_filter_chan_len)
@@ -519,7 +520,8 @@
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
if (samples_in_hand <= half_filter_chan_len)
- { prepare_data (filter, data, half_filter_chan_len) ;
+ { if ((psrc->error = prepare_data (filter, data, half_filter_chan_len)) != 0)
+ return psrc->error ;
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
if (samples_in_hand <= half_filter_chan_len)
@@ -672,7 +674,8 @@
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
if (samples_in_hand <= half_filter_chan_len)
- { prepare_data (filter, data, half_filter_chan_len) ;
+ { if ((psrc->error = prepare_data (filter, data, half_filter_chan_len)) != 0)
+ return psrc->error ;
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
if (samples_in_hand <= half_filter_chan_len)
@@ -831,7 +834,8 @@
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
if (samples_in_hand <= half_filter_chan_len)
- { prepare_data (filter, data, half_filter_chan_len) ;
+ { if ((psrc->error = prepare_data (filter, data, half_filter_chan_len)) != 0)
+ return psrc->error ;
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
if (samples_in_hand <= half_filter_chan_len)
@@ -1077,7 +1081,8 @@
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
if (samples_in_hand <= half_filter_chan_len)
- { prepare_data (filter, data, half_filter_chan_len) ;
+ { if ((psrc->error = prepare_data (filter, data, half_filter_chan_len)) != 0)
+ return psrc->error ;
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
if (samples_in_hand <= half_filter_chan_len)
@@ -1126,12 +1131,12 @@
/*----------------------------------------------------------------------------------------
*/
-static void
+static int
prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len)
{ int len = 0 ;
if (filter->b_real_end >= 0)
- return ; /* This doesn't make sense, so return. */
+ return 0 ; /* Should be terminating. Just return. */
if (filter->b_current == 0)
{ /* Initial state. Set up zeros at the start of the buffer and
@@ -1161,6 +1166,9 @@
len = MIN (filter->in_count - filter->in_used, len) ;
len -= (len % filter->channels) ;
+ if (len < 0 || filter->b_end + len > filter->b_len)
+ return SRC_ERR_SINC_PREPARE_DATA_BAD_LEN ;
+
memcpy (filter->buffer + filter->b_end, data->data_in + filter->in_used,
len * sizeof (filter->buffer [0])) ;
@@ -1190,7 +1198,7 @@
filter->b_end += len ;
} ;
- return ;
+ return 0 ;
} /* prepare_data */