From 4d7945f77871c2aeb1a2e702d03711db635ea472 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Fri, 30 May 2025 07:01:03 -0500 Subject: [PATCH] XM import: possibly fix crash thanks LTVA for diagnosis issue #2453 --- src/engine/fileOps/xm.cpp | 42 +++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/src/engine/fileOps/xm.cpp b/src/engine/fileOps/xm.cpp index 1e7330489..7579c04b5 100644 --- a/src/engine/fileOps/xm.cpp +++ b/src/engine/fileOps/xm.cpp @@ -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) { struct InvalidHeaderException {}; bool success=false; char magic[32]; - unsigned char sampleVol[256][256]; - unsigned char samplePan[256][256]; - unsigned char noteMap[256][128]; + unsigned char* sampleVol=new unsigned char[256*256]; + unsigned char* samplePan=new unsigned char[256*256]; + unsigned char* noteMap=new unsigned char[256*128]; unsigned short patLen[256]; @@ -216,6 +221,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { logE("premature end of file!"); lastError="incomplete file"; delete[] file; + XM_FINISH; return false; } reader.read(magic,17); @@ -255,6 +261,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { logE("invalid order count!"); lastError="invalid order count"; delete[] file; + XM_FINISH; return false; } @@ -262,6 +269,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { logE("too many patterns!"); lastError="too many patterns"; delete[] file; + XM_FINISH; return false; } @@ -269,6 +277,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { logE("invalid instrument count!"); lastError="invalid instrument count"; delete[] file; + XM_FINISH; return false; } @@ -278,6 +287,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { logE("invalid channel count!"); lastError="invalid channel count"; delete[] file; + XM_FINISH; return false; } @@ -306,6 +316,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { logE("premature end of file!"); lastError="incomplete file"; delete[] file; + XM_FINISH; return false; } @@ -322,6 +333,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { lastError="unknown packing type"; ds.unload(); delete[] file; + XM_FINISH; return false; } @@ -334,6 +346,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { logE("too many rows! %d",totalRows); lastError="too many rows"; delete[] file; + XM_FINISH; return false; } @@ -344,6 +357,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { logE("premature end of file!"); lastError="incomplete file"; delete[] file; + XM_FINISH; return false; } @@ -491,6 +505,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { logE("premature end of file!"); lastError="incomplete file"; delete[] file; + XM_FINISH; return false; } } @@ -518,6 +533,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { delete ins; song.unload(); delete[] file; + XM_FINISH; return false; }*/ @@ -532,7 +548,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { for (int j=0; j<96; j++) { unsigned char nextMap=reader.readC(); 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++) { @@ -611,6 +627,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { logE("premature end of file!"); lastError="incomplete file"; delete[] file; + XM_FINISH; return false; } @@ -625,17 +642,18 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { lastError="bad sample size"; delete s; delete[] file; + XM_FINISH; return false; } s->loopStart=reader.readI(); s->loopEnd=reader.readI()+s->loopStart; - sampleVol[i][j]=reader.readC(); + sampleVol[(i<<8)|j]=reader.readC(); signed char fine=reader.readC(); unsigned char flags=reader.readC(); - samplePan[i][j]=reader.readC(); + samplePan[(i<<8)|j]=reader.readC(); signed char note=reader.readC(); switch (flags&3) { @@ -706,6 +724,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { logE("premature end of file!"); lastError="incomplete file"; delete[] file; + XM_FINISH; return false; } } @@ -717,6 +736,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { logE("premature end of file!"); lastError="incomplete file"; delete[] file; + XM_FINISH; return false; } @@ -799,6 +819,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { lastError="unknown packing type"; ds.unload(); delete[] file; + XM_FINISH; return false; } @@ -811,6 +832,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { logE("too many rows! %d",totalRows); lastError="too many rows"; delete[] file; + XM_FINISH; return false; } @@ -821,6 +843,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { logE("premature end of file!"); lastError="incomplete file"; delete[] file; + XM_FINISH; return false; } @@ -880,7 +903,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { p->data[j][2]=((int)ins)-1; // default volume 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; } @@ -1189,7 +1212,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { if (writePanning && hasNote && note<96 && ins>0) { 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!"); lastError="incomplete file"; delete[] file; + XM_FINISH; return false; } } @@ -1315,6 +1339,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { lastError="too many samples"; ds.unload(); delete[] file; + XM_FINISH; return false; } @@ -1351,6 +1376,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { //logE("invalid header!"); lastError="invalid header!"; } + XM_FINISH; return success; }