summaryrefslogtreecommitdiffstats
path: root/apps/plugins/mikmod/load_xm.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/mikmod/load_xm.c')
-rw-r--r--apps/plugins/mikmod/load_xm.c129
1 files changed, 70 insertions, 59 deletions
diff --git a/apps/plugins/mikmod/load_xm.c b/apps/plugins/mikmod/load_xm.c
index ffbd6dff4d..3eb0803668 100644
--- a/apps/plugins/mikmod/load_xm.c
+++ b/apps/plugins/mikmod/load_xm.c
@@ -6,12 +6,12 @@
it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Library General Public License for more details.
-
+
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -20,7 +20,7 @@
/*==============================================================================
- $Id: load_xm.c,v 1.5 2008/02/29 18:49:03 denis111 Exp $
+ $Id$
Fasttracker (XM) module loader
@@ -59,7 +59,7 @@ typedef struct XMHEADER {
UWORD numchn; /* Number of channels (2,4,6,8,10,...,32) */
UWORD numpat; /* Number of patterns (max 256) */
UWORD numins; /* Number of instruments (max 128) */
- UWORD flags;
+ UWORD flags;
UWORD tempo; /* Default tempo */
UWORD bpm; /* Default BPM */
UBYTE orders[256]; /* Pattern order table */
@@ -129,7 +129,7 @@ typedef struct XMNOTE {
static XMNOTE *xmpat=NULL;
static XMHEADER *mh=NULL;
-/* increment unit for sample array MikMod_reallocation */
+/* increment unit for sample array reallocation */
#define XM_SMPINCR 64
static ULONG *nextwav=NULL;
static XMWAVHEADER *wh=NULL,*s=NULL;
@@ -155,6 +155,7 @@ static int XM_Init(void)
static void XM_Cleanup(void)
{
MikMod_free(mh);
+ mh=NULL;
}
static int XM_ReadNote(XMNOTE* n)
@@ -359,8 +360,8 @@ static int LoadPatterns(int dummypat)
return 0;
/* when packsize is 0, don't try to load a pattern.. it's empty. */
- if(ph.packsize)
- for(u=0;u<ph.numrows;u++)
+ if(ph.packsize)
+ for(u=0;u<ph.numrows;u++)
for(v=0;v<of.numchn;v++) {
if(!ph.packsize) break;
@@ -443,11 +444,17 @@ static void FixEnvelope(ENVPT *cur, int pts)
static int LoadInstruments(void)
{
- int t,u, ck;
+ long filend,ck;
+ int t,u;
INSTRUMENT *d;
ULONG next=0;
UWORD wavcnt=0;
+ ck = _mm_ftell(modreader);
+ _mm_fseek(modreader,0,SEEK_END);
+ filend = _mm_ftell(modreader);
+ _mm_fseek(modreader,ck,SEEK_SET);
+
if(!AllocInstruments()) return 0;
d=of.instruments;
for(t=0;t<of.numins;t++,d++) {
@@ -461,12 +468,9 @@ static int LoadInstruments(void)
ih.size = _mm_read_I_ULONG(modreader);
headend += ih.size;
ck = _mm_ftell(modreader);
- _mm_fseek(modreader,0,SEEK_END);
- if ((headend<0) || (_mm_ftell(modreader)<headend) || (headend<ck)) {
- _mm_fseek(modreader,ck,SEEK_SET);
+ if ((headend<0) || (filend<headend) || (headend<ck)) {
break;
}
- _mm_fseek(modreader,ck,SEEK_SET);
_mm_read_string(ih.name, 22, modreader);
ih.type = _mm_read_UBYTE(modreader);
ih.numsmp = _mm_read_I_UWORD(modreader);
@@ -500,7 +504,11 @@ static int LoadInstruments(void)
/* read the remainder of the header
(2 bytes for 1.03, 22 for 1.04) */
- if (headend>=_mm_ftell(modreader)) for(u=headend-_mm_ftell(modreader);u;u--) (void)_mm_read_UBYTE(modreader);
+ if (headend>=_mm_ftell(modreader)) {
+ for(u=headend-_mm_ftell(modreader);u;u--) {
+ _mm_skip_BYTE(modreader);
+ }
+ }
/* we can't trust the envelope point count here, as some
modules have incorrect values (K_OSPACE.XM reports 32 volume
@@ -509,8 +517,8 @@ static int LoadInstruments(void)
if(pth.panpts>XMENVCNT/2) pth.panpts=XMENVCNT/2;
if((_mm_eof(modreader))||(pth.volpts>XMENVCNT/2)||(pth.panpts>XMENVCNT/2)) {
- if(nextwav) { MikMod_free(nextwav);nextwav=NULL; }
- if(wh) { MikMod_free(wh);wh=NULL; }
+ MikMod_free(nextwav);nextwav=NULL;
+ MikMod_free(wh);wh=NULL;
_mm_errno = MMERR_LOADING_SAMPLEINFO;
return 0;
}
@@ -519,7 +527,7 @@ static int LoadInstruments(void)
d->samplenumber[u]=pth.what[u]+of.numsmp;
d->volfade = pth.volfade;
-#if defined __STDC__ || defined _MSC_VER || defined MPW_C
+#if defined __STDC__ || defined _MSC_VER || defined __WATCOMC__ || defined MPW_C
#define XM_ProcessEnvelope(name) \
for (u = 0; u < (XMENVCNT >> 1); u++) { \
d-> name##env[u].pos = pth. name##env[u << 1]; \
@@ -560,7 +568,7 @@ static int LoadInstruments(void)
\
if ((d-> name/**/flg&EF_ON)&&(d-> name/**/pts<2)) \
d-> name/**/flg&=~EF_ON
-#endif
+#endif
XM_ProcessEnvelope(vol);
XM_ProcessEnvelope(pan);
@@ -577,15 +585,23 @@ static int LoadInstruments(void)
everything over */
if(mh->version>0x0103) next = 0;
for(u=0;u<ih.numsmp;u++,s++) {
+ /* XM sample header is 40 bytes: make sure we won't hit EOF */
+ /* Note: last instrument is at the end of file in version 0x0104 */
+ if(_mm_ftell(modreader)+40>filend) {
+ MikMod_free(nextwav);MikMod_free(wh);
+ nextwav=NULL;wh=NULL;
+ _mm_errno = MMERR_LOADING_SAMPLEINFO;
+ return 0;
+ }
/* Allocate more room for sample information if necessary */
if(of.numsmp+u==wavcnt) {
wavcnt+=XM_SMPINCR;
- if(!(nextwav=MikMod_realloc(nextwav,wavcnt*sizeof(ULONG)))){
- if(wh) { MikMod_free(wh);wh=NULL; }
+ if(!(nextwav=(ULONG*)MikMod_realloc(nextwav,wavcnt*sizeof(ULONG)))){
+ MikMod_free(wh);wh=NULL;
_mm_errno = MMERR_OUT_OF_MEMORY;
return 0;
}
- if(!(wh=MikMod_realloc(wh,wavcnt*sizeof(XMWAVHEADER)))) {
+ if(!(wh=(XMWAVHEADER*)MikMod_realloc(wh,wavcnt*sizeof(XMWAVHEADER)))) {
MikMod_free(nextwav);nextwav=NULL;
_mm_errno = MMERR_OUT_OF_MEMORY;
return 0;
@@ -610,13 +626,6 @@ static int LoadInstruments(void)
nextwav[of.numsmp+u]=next;
next+=s->length;
-
- if(_mm_eof(modreader)) {
- MikMod_free(nextwav);MikMod_free(wh);
- nextwav=NULL;wh=NULL;
- _mm_errno = MMERR_LOADING_SAMPLEINFO;
- return 0;
- }
}
if(mh->version>0x0103) {
@@ -628,15 +637,15 @@ static int LoadInstruments(void)
} else {
/* read the remainder of the header */
ck = _mm_ftell(modreader);
- _mm_fseek(modreader,0,SEEK_END);
- if ((headend<0) || (_mm_ftell(modreader)<headend) || (headend<ck)) {
- _mm_fseek(modreader,ck,SEEK_SET);
+ if ((headend<0) || (filend<headend) || (headend<ck)) {
break;
}
- _mm_fseek(modreader,ck,SEEK_SET);
- for(u=headend-_mm_ftell(modreader);u;u--) (void)_mm_read_UBYTE(modreader);
+ for(u=headend-_mm_ftell(modreader);u;u--) {
+ _mm_skip_BYTE(modreader);
+ }
- if(_mm_eof(modreader)) {
+ /* last instrument is at the end of file in version 0x0104 */
+ if(_mm_eof(modreader) && (mh->version<0x0104 || t<of.numins-1)) {
MikMod_free(nextwav);MikMod_free(wh);
nextwav=NULL;wh=NULL;
_mm_errno = MMERR_LOADING_SAMPLEINFO;
@@ -648,8 +657,8 @@ static int LoadInstruments(void)
/* sanity check */
if(!of.numsmp) {
- if(nextwav) { MikMod_free(nextwav);nextwav=NULL; }
- if(wh) { MikMod_free(wh);wh=NULL; }
+ MikMod_free(nextwav);nextwav=NULL;
+ MikMod_free(wh);wh=NULL;
_mm_errno = MMERR_LOADING_SAMPLEINFO;
return 0;
}
@@ -664,17 +673,15 @@ static int XM_Load(int curious)
int t,u;
int dummypat=0;
char tracker[21],modtype[60];
- (void)curious;
+ (void)curious;
/* try to read module header */
_mm_read_string(mh->id,17,modreader);
_mm_read_string(mh->songname,21,modreader);
_mm_read_string(mh->trackername,20,modreader);
mh->version =_mm_read_I_UWORD(modreader);
- if((mh->version<0x102)||(mh->version>0x104)) {
- _mm_errno=MMERR_NOT_A_MODULE;
- return 0;
- }
+ if(mh->version < 0x102 || mh->version > 0x104)
+ goto bad_xm;
mh->headersize =_mm_read_I_ULONG(modreader);
mh->songlength =_mm_read_I_UWORD(modreader);
mh->restart =_mm_read_I_UWORD(modreader);
@@ -684,23 +691,25 @@ static int XM_Load(int curious)
mh->flags =_mm_read_I_UWORD(modreader);
mh->tempo =_mm_read_I_UWORD(modreader);
mh->bpm =_mm_read_I_UWORD(modreader);
- if(!mh->bpm) {
- _mm_errno=MMERR_NOT_A_MODULE;
- return 0;
- }
- _mm_read_UBYTES(mh->orders,mh->headersize-20,modreader);
-
- if(_mm_eof(modreader)) {
- _mm_errno = MMERR_LOADING_HEADER;
- return 0;
- }
+ if(mh->numchn > 64) goto bad_xm;
+ if(mh->tempo > 32 || mh->bpm < 32 || mh->bpm > 255)
+ goto bad_xm;
+ if(mh->songlength > 256 || mh->headersize < 20 || mh->headersize > 20+256)
+ goto bad_xm;
+ if(mh->numpat > 256 || mh->numins > 255 || mh->restart > 255)
+ goto bad_xm;
+/* _mm_read_UBYTES(mh->orders,256,modreader);*/
+/* _mm_read_UBYTES(mh->orders,mh->headersize-20,modreader);*/
+ _mm_read_UBYTES(mh->orders,mh->songlength,modreader);
+ if(_mm_fseek(modreader, mh->headersize+60, SEEK_SET) || _mm_eof(modreader))
+ goto bad_hdr;
/* set module variables */
- of.initspeed = mh->tempo;
+ of.initspeed = mh->tempo;
of.inittempo = mh->bpm;
strncpy(tracker,mh->trackername,20);tracker[20]=0;
- for(t=20;(tracker[t]<=' ')&&(t>=0);t--) tracker[t]=0;
-
+ for(t=20;(t>=0)&&(tracker[t]<=' ');t--) tracker[t]=0;
+
/* some modules have the tracker name empty */
if (!tracker[0])
strcpy(tracker,"Unknown tracker");
@@ -712,7 +721,7 @@ static int XM_Load(int curious)
sprintf(modtype,"%s (XM format %d.%02d)",
tracker,mh->version>>8,mh->version&0xff);
#endif
- of.modtype = StrDup(modtype);
+ of.modtype = MikMod_strdup(modtype);
of.numchn = mh->numchn;
of.numpat = mh->numpat;
of.numtrk = (UWORD)of.numpat*of.numchn; /* get number of channels */
@@ -720,8 +729,7 @@ static int XM_Load(int curious)
of.numpos = mh->songlength; /* copy the songlength */
of.reppos = mh->restart<mh->songlength?mh->restart:0;
of.numins = mh->numins;
- of.flags |= UF_XMPERIODS | UF_INST | UF_NOWRAP | UF_FT2QUIRKS |
- UF_PANNING;
+ of.flags |= UF_XMPERIODS | UF_INST | UF_NOWRAP | UF_FT2QUIRKS | UF_PANNING;
if(mh->flags&1) of.flags |= UF_LINEAR;
of.bpmlimit = 32;
@@ -802,16 +810,19 @@ static int XM_Load(int curious)
MikMod_free(wh);MikMod_free(nextwav);
wh=NULL;nextwav=NULL;
return 1;
+
+bad_hdr: _mm_errno = MMERR_LOADING_HEADER; return 0;
+bad_xm: _mm_errno = MMERR_NOT_A_MODULE; return 0;
}
static CHAR *XM_LoadTitle(void)
{
- CHAR s[21];
+ CHAR str[21];
_mm_fseek(modreader,17,SEEK_SET);
- if(!_mm_read_UBYTES(s,21,modreader)) return NULL;
+ if(!_mm_read_UBYTES(str, 21, modreader)) return NULL;
- return(DupStr(s,21,1));
+ return(DupStr(str,21,1));
}
/*========== Loader information */