mirror of
https://github.com/OldUnreal/libxmp.git
synced 2026-04-02 21:37:43 -07:00
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:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user