XM import: possibly fix crash

thanks LTVA for diagnosis
issue #2453
This commit is contained in:
tildearrow 2025-05-30 07:01:03 -05:00
parent 01348628a8
commit 4d7945f778

View file

@ -162,13 +162,18 @@ void readEnvelope(DivInstrument* ins, int env, unsigned char flags, unsigned cha
} }
} }
#define XM_FINISH \
delete[] sampleVol; \
delete[] samplePan; \
delete[] noteMap;
bool DivEngine::loadXM(unsigned char* file, size_t len) { bool DivEngine::loadXM(unsigned char* file, size_t len) {
struct InvalidHeaderException {}; struct InvalidHeaderException {};
bool success=false; bool success=false;
char magic[32]; char magic[32];
unsigned char sampleVol[256][256]; unsigned char* sampleVol=new unsigned char[256*256];
unsigned char samplePan[256][256]; unsigned char* samplePan=new unsigned char[256*256];
unsigned char noteMap[256][128]; unsigned char* noteMap=new unsigned char[256*128];
unsigned short patLen[256]; unsigned short patLen[256];
@ -216,6 +221,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
logE("premature end of file!"); logE("premature end of file!");
lastError="incomplete file"; lastError="incomplete file";
delete[] file; delete[] file;
XM_FINISH;
return false; return false;
} }
reader.read(magic,17); reader.read(magic,17);
@ -255,6 +261,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
logE("invalid order count!"); logE("invalid order count!");
lastError="invalid order count"; lastError="invalid order count";
delete[] file; delete[] file;
XM_FINISH;
return false; return false;
} }
@ -262,6 +269,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
logE("too many patterns!"); logE("too many patterns!");
lastError="too many patterns"; lastError="too many patterns";
delete[] file; delete[] file;
XM_FINISH;
return false; return false;
} }
@ -269,6 +277,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
logE("invalid instrument count!"); logE("invalid instrument count!");
lastError="invalid instrument count"; lastError="invalid instrument count";
delete[] file; delete[] file;
XM_FINISH;
return false; return false;
} }
@ -278,6 +287,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
logE("invalid channel count!"); logE("invalid channel count!");
lastError="invalid channel count"; lastError="invalid channel count";
delete[] file; delete[] file;
XM_FINISH;
return false; return false;
} }
@ -306,6 +316,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
logE("premature end of file!"); logE("premature end of file!");
lastError="incomplete file"; lastError="incomplete file";
delete[] file; delete[] file;
XM_FINISH;
return false; return false;
} }
@ -322,6 +333,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
lastError="unknown packing type"; lastError="unknown packing type";
ds.unload(); ds.unload();
delete[] file; delete[] file;
XM_FINISH;
return false; return false;
} }
@ -334,6 +346,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
logE("too many rows! %d",totalRows); logE("too many rows! %d",totalRows);
lastError="too many rows"; lastError="too many rows";
delete[] file; delete[] file;
XM_FINISH;
return false; return false;
} }
@ -344,6 +357,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
logE("premature end of file!"); logE("premature end of file!");
lastError="incomplete file"; lastError="incomplete file";
delete[] file; delete[] file;
XM_FINISH;
return false; return false;
} }
@ -491,6 +505,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
logE("premature end of file!"); logE("premature end of file!");
lastError="incomplete file"; lastError="incomplete file";
delete[] file; delete[] file;
XM_FINISH;
return false; return false;
} }
} }
@ -518,6 +533,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
delete ins; delete ins;
song.unload(); song.unload();
delete[] file; delete[] file;
XM_FINISH;
return false; return false;
}*/ }*/
@ -532,7 +548,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
for (int j=0; j<96; j++) { for (int j=0; j<96; j++) {
unsigned char nextMap=reader.readC(); unsigned char nextMap=reader.readC();
ins->amiga.noteMap[j].map=ds.sample.size()+nextMap; ins->amiga.noteMap[j].map=ds.sample.size()+nextMap;
noteMap[i][j]=nextMap; noteMap[(i<<7)|j]=nextMap;
} }
for (int j=0; j<24; j++) { for (int j=0; j<24; j++) {
@ -611,6 +627,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
logE("premature end of file!"); logE("premature end of file!");
lastError="incomplete file"; lastError="incomplete file";
delete[] file; delete[] file;
XM_FINISH;
return false; return false;
} }
@ -625,17 +642,18 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
lastError="bad sample size"; lastError="bad sample size";
delete s; delete s;
delete[] file; delete[] file;
XM_FINISH;
return false; return false;
} }
s->loopStart=reader.readI(); s->loopStart=reader.readI();
s->loopEnd=reader.readI()+s->loopStart; s->loopEnd=reader.readI()+s->loopStart;
sampleVol[i][j]=reader.readC(); sampleVol[(i<<8)|j]=reader.readC();
signed char fine=reader.readC(); signed char fine=reader.readC();
unsigned char flags=reader.readC(); unsigned char flags=reader.readC();
samplePan[i][j]=reader.readC(); samplePan[(i<<8)|j]=reader.readC();
signed char note=reader.readC(); signed char note=reader.readC();
switch (flags&3) { switch (flags&3) {
@ -706,6 +724,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
logE("premature end of file!"); logE("premature end of file!");
lastError="incomplete file"; lastError="incomplete file";
delete[] file; delete[] file;
XM_FINISH;
return false; return false;
} }
} }
@ -717,6 +736,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
logE("premature end of file!"); logE("premature end of file!");
lastError="incomplete file"; lastError="incomplete file";
delete[] file; delete[] file;
XM_FINISH;
return false; return false;
} }
@ -799,6 +819,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
lastError="unknown packing type"; lastError="unknown packing type";
ds.unload(); ds.unload();
delete[] file; delete[] file;
XM_FINISH;
return false; return false;
} }
@ -811,6 +832,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
logE("too many rows! %d",totalRows); logE("too many rows! %d",totalRows);
lastError="too many rows"; lastError="too many rows";
delete[] file; delete[] file;
XM_FINISH;
return false; return false;
} }
@ -821,6 +843,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
logE("premature end of file!"); logE("premature end of file!");
lastError="incomplete file"; lastError="incomplete file";
delete[] file; delete[] file;
XM_FINISH;
return false; return false;
} }
@ -880,7 +903,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
p->data[j][2]=((int)ins)-1; p->data[j][2]=((int)ins)-1;
// default volume // default volume
if (lastNote[k]<96 && ins>0) { if (lastNote[k]<96 && ins>0) {
p->data[j][3]=sampleVol[(ins-1)&255][noteMap[(ins-1)&255][lastNote[k]&127]]; p->data[j][3]=sampleVol[(((ins-1)&255)<<8)|(noteMap[(((ins-1)&255)<<7)|(lastNote[k]&127)])];
} }
writePanning=true; writePanning=true;
} }
@ -1189,7 +1212,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
if (writePanning && hasNote && note<96 && ins>0) { if (writePanning && hasNote && note<96 && ins>0) {
p->data[j][effectCol[k]++]=0x80; p->data[j][effectCol[k]++]=0x80;
p->data[j][effectCol[k]++]=samplePan[(ins-1)&255][noteMap[(ins-1)&255][note&127]]; p->data[j][effectCol[k]++]=samplePan[(((ins-1)&255)<<8)|(noteMap[(((ins-1)&255)<<7)|(note&127)])];
} }
} }
@ -1305,6 +1328,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
logE("premature end of file!"); logE("premature end of file!");
lastError="incomplete file"; lastError="incomplete file";
delete[] file; delete[] file;
XM_FINISH;
return false; return false;
} }
} }
@ -1315,6 +1339,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
lastError="too many samples"; lastError="too many samples";
ds.unload(); ds.unload();
delete[] file; delete[] file;
XM_FINISH;
return false; return false;
} }
@ -1351,6 +1376,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
//logE("invalid header!"); //logE("invalid header!");
lastError="invalid header!"; lastError="invalid header!";
} }
XM_FINISH;
return success; return success;
} }