Fix MEDs with pattern lengths >256, MED instrument corruption.

Adds a new function to allow MEDs with block lengths >256 to use
a relaxed row limit and adds MED-specific sanity checks for block
lengths (3200 for Amiga MEDs, 9999 for MED Soundstudio 2).

Also fixes an issue with MED instrument name loading that would cause
the instrument volume and number of samples to get corrupted.
This commit is contained in:
AliceLR
2020-11-03 14:33:23 -07:00
committed by Ozkan Sezer
parent b387f381b9
commit a07c760ae9
4 changed files with 47 additions and 10 deletions

View File

@@ -138,7 +138,27 @@ int libxmp_alloc_tracks_in_pattern(struct xmp_module *mod, int num)
int libxmp_alloc_pattern_tracks(struct xmp_module *mod, int num, int rows)
{
/* Sanity check */
if (rows < 0 || rows > 256)
if (rows <= 0 || rows > 256)
return -1;
if (libxmp_alloc_pattern(mod, num) < 0)
return -1;
mod->xxp[num]->rows = rows;
if (libxmp_alloc_tracks_in_pattern(mod, num) < 0)
return -1;
return 0;
}
/* Some formats explicitly allow more than 256 rows (e.g. OctaMED). This function
* allows those formats to work without disrupting the sanity check for other formats.
*/
int libxmp_alloc_pattern_tracks_long(struct xmp_module *mod, int num, int rows)
{
/* Sanity check */
if (rows <= 0 || rows > 32768)
return -1;
if (libxmp_alloc_pattern(mod, num) < 0)

View File

@@ -32,6 +32,7 @@ int libxmp_alloc_pattern (struct xmp_module *, int);
int libxmp_alloc_track (struct xmp_module *, int, int);
int libxmp_alloc_tracks_in_pattern (struct xmp_module *, int);
int libxmp_alloc_pattern_tracks (struct xmp_module *, int, int);
int libxmp_alloc_pattern_tracks_long(struct xmp_module *, int, int);
char *libxmp_instrument_name (struct xmp_module *, int, uint8 *, int);
struct xmp_sample* libxmp_realloc_samples(struct xmp_sample *, int *, int);

View File

@@ -92,6 +92,7 @@ static int mmd1_load(struct module_data *m, HIO_HANDLE *f, const int start)
int annotxt_offset;
int pos;
int bpm_on, bpmlen, med_8ch, hexvol;
char name[40];
LOAD_INIT();
@@ -348,7 +349,11 @@ static int mmd1_load(struct module_data *m, HIO_HANDLE *f, const int start)
block.lines = hio_read8(f);
}
if (libxmp_alloc_pattern_tracks(mod, i, block.lines + 1) < 0)
/* Sanity check--Amiga OctaMED files have an upper bound of 3200 lines per block. */
if (block.lines + 1 > 3200)
return -1;
if (libxmp_alloc_pattern_tracks_long(mod, i, block.lines + 1) < 0)
return -1;
if (ver > 0) { /* MMD1 */
@@ -451,11 +456,13 @@ static int mmd1_load(struct module_data *m, HIO_HANDLE *f, const int start)
if (expdata_offset && i < expdata.i_ext_entries) {
struct xmp_instrument *xxi = &mod->xxi[i];
int offset = iinfo_offset + i * expdata.i_ext_entrsz;
if (offset < 0 || hio_seek(f, offset, SEEK_SET) < 0) {
if (offset < 0 || hio_seek(f, start + offset, SEEK_SET) < 0) {
return -1;
}
hio_read(xxi->name, 40, 1, f);
hio_read(name, 40, 1, f);
strncpy(xxi->name, name, 32);
xxi->name[31] = '\0';
}
D_(D_INFO "[%2x] %-40.40s %d", i, mod->xxi[i].name, instr.type);
@@ -464,7 +471,7 @@ static int mmd1_load(struct module_data *m, HIO_HANDLE *f, const int start)
if (expdata_offset && i < expdata.s_ext_entries) {
int offset = expsmp_offset + i * expdata.s_ext_entrsz;
if (offset < 0 || hio_seek(f, offset, SEEK_SET) < 0) {
if (offset < 0 || hio_seek(f, start + offset, SEEK_SET) < 0) {
return -1;
}
exp_smp.hold = hio_read8(f);

View File

@@ -92,6 +92,7 @@ static int mmd3_load(struct module_data *m, HIO_HANDLE *f, const int start)
int playseq_offset;
int pos;
int bpm_on, bpmlen, med_8ch, hexvol;
char name[40];
LOAD_INIT();
@@ -349,7 +350,13 @@ static int mmd3_load(struct module_data *m, HIO_HANDLE *f, const int start)
block.lines = hio_read16b(f);
hio_read32b(f);
if (libxmp_alloc_pattern_tracks(mod, i, block.lines + 1) < 0)
/* Sanity check--Amiga OctaMED files have an upper bound of 3200 lines per block,
* but MED Soundstudio for Windows allows up to 9999 lines.
*/
if (block.lines + 1 > 9999)
return -1;
if (libxmp_alloc_pattern_tracks_long(mod, i, block.lines + 1) < 0)
return -1;
for (j = 0; j < mod->xxp[i]->rows; j++) {
@@ -424,10 +431,12 @@ static int mmd3_load(struct module_data *m, HIO_HANDLE *f, const int start)
struct xmp_instrument *xxi = &mod->xxi[i];
int offset = iinfo_offset + i * expdata.i_ext_entrsz;
if (offset < 0 || hio_seek(f, offset, SEEK_SET) < 0) {
if (offset < 0 || hio_seek(f, start + offset, SEEK_SET) < 0) {
return -1;
}
hio_read(xxi->name, 40, 1, f);
hio_read(name, 40, 1, f);
strncpy(xxi->name, name, 32);
xxi->name[31] = '\0';
D_(D_INFO "[%2x] %-40.40s %d", i, mod->xxi[i].name, instr.type);
}
@@ -436,7 +445,7 @@ static int mmd3_load(struct module_data *m, HIO_HANDLE *f, const int start)
if (expdata_offset && i < expdata.s_ext_entries) {
int offset = expsmp_offset + i * expdata.s_ext_entrsz;
if (offset < 0 || hio_seek(f, offset, SEEK_SET) < 0) {
if (offset < 0 || hio_seek(f, start + offset, SEEK_SET) < 0) {
return -1;
}
exp_smp.hold = hio_read8(f);