shithub: libsamplerate

Download patch

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 */