shithub: dumb

Download patch

ref: d2575fcc80abf2f04e702adb60a6265cef0fcabb
parent: b17c5254eeac1bff7e4b613c151e0232c2cba646
author: Chris Moeller <kode54@gmail.com>
date: Mon Dec 3 22:49:30 EST 2012

- Implemented final solution for MOD pattern count calculation
- Fixed possible memory leak which only would have occurred with rare MOD files
- Fixed a possible memory allocation error or crash with FLT8 MOD files

--- a/dumb/src/it/readmod.c
+++ b/dumb/src/it/readmod.c
@@ -629,13 +629,44 @@
 	if (sigdata->n_samples == 31)
 		dumbfile_skip(f, 4);
 
-	/* Work out how many patterns there are. */
 	sigdata->n_patterns = -1;
-	for (i = 0; i < sigdata->n_orders; i++)
-		if (sigdata->n_patterns < sigdata->order[i])
-			sigdata->n_patterns = sigdata->order[i];
-	sigdata->n_patterns++;
 
+	{
+		long total_sample_size;
+		long remain;
+		rem = f;
+		f = dumbfile_buffer_mod_2(rem, &remain);
+		if (!f) {
+			_dumb_it_unload_sigdata(sigdata);
+			dumbfile_close(rem);
+			return NULL;
+		}
+		for (total_sample_size = 0, i = 0; i < sigdata->n_samples; i++) {
+			if (sigdata->sample[i].flags & IT_SAMPLE_EXISTS) {
+				total_sample_size += sigdata->sample[i].length;
+			}
+		}
+		if (remain > total_sample_size) {
+			sigdata->n_patterns = ( remain - total_sample_size ) / ( 256 * sigdata->n_pchannels );
+			if (fft == DUMB_ID('M',0,0,0) || fft == DUMB_ID('8',0,0,0)) {
+				remain -= sigdata->n_patterns * 256 * sigdata->n_pchannels;
+				if (dumbfile_skip(f, remain - total_sample_size)) {
+					_dumb_it_unload_sigdata(sigdata);
+					dumbfile_close(f);
+					dumbfile_close(rem);
+					return NULL;
+				}
+			}
+		}
+	}
+
+	if ( sigdata->n_patterns <= 0 ) {
+		_dumb_it_unload_sigdata(sigdata);
+		dumbfile_close(f);
+		dumbfile_close(rem);
+		return NULL;
+	}
+
 	/* May as well try to save a tiny bit of memory. */
 	if (sigdata->n_orders < 128) {
 		unsigned char *order = realloc(sigdata->order, sigdata->n_orders);
@@ -646,6 +677,7 @@
 	if (!sigdata->pattern) {
 		_dumb_it_unload_sigdata(sigdata);
 		dumbfile_close(f);
+		dumbfile_close(rem);
 		return NULL;
 	}
 	for (i = 0; i < sigdata->n_patterns; i++)
@@ -653,10 +685,11 @@
 
 	/* Read in the patterns */
 	{
-		unsigned char *buffer = malloc(256 * n_channels); /* 64 rows * 4 bytes */
+		unsigned char *buffer = malloc(256 * sigdata->n_pchannels); /* 64 rows * 4 bytes */
 		if (!buffer) {
 			_dumb_it_unload_sigdata(sigdata);
 			dumbfile_close(f);
+			dumbfile_close(rem);
 			return NULL;
 		}
 		for (i = 0; i < sigdata->n_patterns; i++) {
@@ -664,6 +697,7 @@
 				free(buffer);
 				_dumb_it_unload_sigdata(sigdata);
 				dumbfile_close(f);
+				dumbfile_close(rem);
 				return NULL;
 			}
 		}
@@ -670,40 +704,12 @@
 		free(buffer);
 	}
 
-	rem = NULL;
-
-	/* uggly */
-	if (fft == DUMB_ID('M',0,0,0) || fft == DUMB_ID('8',0,0,0)) {
-		long skip;
-		long remain;
-		rem = f;
-		f = dumbfile_buffer_mod_2(rem, &remain);
-		if (!f) {
-			_dumb_it_unload_sigdata(sigdata);
-			dumbfile_close(rem);
-			return NULL;
-		}
-		for (skip = 0, i = 0; i < sigdata->n_samples; i++) {
-			if (sigdata->sample[i].flags & IT_SAMPLE_EXISTS) {
-				skip += sigdata->sample[i].length;
-			}
-		}
-		if (remain - skip) {
-			if (dumbfile_skip(f, remain - skip)) {
-				_dumb_it_unload_sigdata(sigdata);
-				dumbfile_close(f);
-				dumbfile_close(rem);
-				return NULL;
-			}
-		}
-	}
-
 	/* And finally, the sample data */
 	for (i = 0; i < sigdata->n_samples; i++) {
 		if (it_mod_read_sample_data(&sigdata->sample[i], f, fft)) {
 			_dumb_it_unload_sigdata(sigdata);
 			dumbfile_close(f);
-			if (rem) dumbfile_close(rem);
+			dumbfile_close(rem);
 			return NULL;
 		}
 	}
@@ -727,8 +733,8 @@
 	}*/
 
 	dumbfile_close(f); /* Destroy the BUFFERED_MOD DUMBFILE we were using. */
+	dumbfile_close(rem); /* And the BUFFERED_MOD DUMBFILE used to pre-read the signature. */
 	/* The DUMBFILE originally passed to our function is intact. */
-	if (rem) dumbfile_close(rem);
 
 	/* Now let's initialise the remaining variables, and we're done! */
 	sigdata->flags = IT_WAS_AN_XM | IT_WAS_A_MOD | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO;