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;