diff --git a/configure.ac b/configure.ac index f96a28e1..bdb195ac 100644 --- a/configure.ac +++ b/configure.ac @@ -1,8 +1,8 @@ dnl Process this file with autoconf to produce a configure script. -AC_PREREQ(2.63) +AC_PREREQ([2.71]) -AC_INIT([libmodplug], [0.8.9.0]) +AC_INIT([libmodplug],[0.8.9.1]) AC_CONFIG_SRCDIR([Makefile.am]) AM_INIT_AUTOMAKE @@ -12,12 +12,6 @@ AC_CONFIG_MACRO_DIR([m4]) AM_MAINTAINER_MODE([enable]) dnl Checks for programs. -dnl I am disabling static libraries here because otherwise libtool insists on -dnl compiling everything twice -- once with and once without -fPIC. Pisses me -dnl off. Just do everything with -fPIC, damnit! Compiling everything twice -dnl probably wastes more cycles than not using -fPIC saves. -AC_DISABLE_STATIC -AC_DISABLE_STATIC([]) AC_PROG_CC AC_PROG_CXX AC_LANG([C++]) @@ -27,7 +21,15 @@ AC_C_BIGENDIAN #AC_PROG_LIBTOOL LT_INIT([win32-dll]) -AC_HEADER_STDC +m4_warn([obsolete], +[The preprocessor macro `STDC_HEADERS' is obsolete. + Except in unusual embedded environments, you can safely include all + ISO C90 headers unconditionally.])dnl +# Autoupdate added the next two lines to ensure that your configure +# script's behavior did not change. They are probably safe to remove. +AC_CHECK_INCLUDES_DEFAULT +AC_PROG_EGREP + AC_CHECK_HEADERS([inttypes.h stdint.h malloc.h]) AC_CHECK_FUNCS(setenv sinf) @@ -55,11 +57,8 @@ esac ac_save_CXXFLAGS="$CXXFLAGS" CXXFLAGS="$CXXFLAGS -fvisibility=hidden -Werror" AC_CACHE_CHECK([if compiler supports visibility attributes],[libmodplug_cv_gcc_visibility], - AC_TRY_COMPILE([void foo(void); -__attribute__((visibility("default"))) void foo(void) {}], - [], - [libmodplug_cv_gcc_visibility=yes], - [libmodplug_cv_gcc_visibility=no]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[void foo(void); +__attribute__((visibility("default"))) void foo(void) {}]], [[]])],[libmodplug_cv_gcc_visibility=yes],[libmodplug_cv_gcc_visibility=no]) ) # we want symbol -fvisibility for elf targets, however it works # with darwin/macho too. other than that, windows, dos and os2 diff --git a/src/load_669.cpp b/src/load_669.cpp index c275615b..c4995b1d 100644 --- a/src/load_669.cpp +++ b/src/load_669.cpp @@ -35,7 +35,7 @@ typedef struct tagSAMPLE669 BYTE loopend[4]; } SAMPLE669; -DWORD lengthArrayToDWORD(const BYTE length[4]) { +static DWORD lengthArrayToDWORD(const BYTE length[4]) { DWORD len = (length[3] << 24) + (length[2] << 16) + (length[1] << 8) + diff --git a/src/load_abc.cpp b/src/load_abc.cpp index ee79f39e..d9b0a41c 100644 --- a/src/load_abc.cpp +++ b/src/load_abc.cpp @@ -810,6 +810,10 @@ static int abc_transpose(const char *v) if( j ) { while( *v && *v != ' ' && *v != ']' ) v++; } + + // Already reached the end of the string.. + if (!*v) + break; } if( strlen(mv) > 0 ) // someone set the middle note t += abc_interval(mv, m); @@ -1282,6 +1286,9 @@ static int abc_add_noteon(ABCHANDLE *h, int ch, const char *p, uint32_t tracktim i = 0; break; } + // nothing good inside - early exit + if ( n == 0 ) + return 0; for( k=0; k<51; k++ ) { if( n == barkey[k] ) break; @@ -1484,7 +1491,7 @@ static void abc_add_chord(const char *p, ABCHANDLE *h, ABCTRACK *tp, uint32_t tr d[chordnote] = i; break; } - p++; + if (*p) p++; switch(*p) { case 'b': d[chordnote]--; @@ -1506,7 +1513,7 @@ static void abc_add_chord(const char *p, ABCHANDLE *h, ABCTRACK *tp, uint32_t tr d[chordbase] = i; break; } - p++; + if (*p) p++; switch(*p) { case 'b': d[chordbase]--; @@ -1655,6 +1662,7 @@ static int abc_notelen(const char *p, int *len, int *div) else k = 1; *div = h * k; if ( *div > 4096 ) *div = 4096; + if ( *div <= 0 ) *div = 1; return i; } @@ -2004,7 +2012,7 @@ static uint32_t abc_fade_tracks(ABCHANDLE *h, char *abcparts, uint32_t ptt[27]) tp->slidevoltime = e0->tracktick; } tp->mute = 0; // unmute track for safety, notes in a muted track already have zero volume... - while( vol > 5 ) { + while( vol > 5 && tp->slidevoltime != 0) { for( p=abcparts; *p && vol > 5; p++ ) { pt1 = ptt[*p-'A']; pt2 = ptt[*p-'A'+1]; @@ -2023,7 +2031,7 @@ static void abc_song_to_parts(ABCHANDLE *h, char **abcparts, BYTE partp[27][2]) ABCEVENT *e; int i, fading, loop, normal, partno, partsegno, partloop, partcoda, parttocoda, partfine, skip, x, y; int vmask[27],nextp[27]; - uint32_t ptt[27]; + uint32_t ptt[27] = {}; char buf[256]; // must be enough, mod's cannot handle more than 240 patterns char *pfade; if( !h || !h->track || !h->track->capostart ) return; @@ -2147,7 +2155,8 @@ static void abc_song_to_parts(ABCHANDLE *h, char **abcparts, BYTE partp[27][2]) if( buf[i] != buf[i-1] + 1 ) { x = buf[i-1] - 'A'; y = buf[i] - 'A'; - abc_keeptiednotes(h, ptt[x+1], ptt[y]); + if (x < 26 && y < 26) + abc_keeptiednotes(h, ptt[x+1], ptt[y]); } } } @@ -2220,6 +2229,8 @@ static void abc_substitute(ABCHANDLE *h, char *target, char *s) strcpy(p,s); for( q=p+l; *q; q++ ) *p++ = *q; } + // ensure end of string is initialized + *p = 0; } } @@ -2239,7 +2250,7 @@ static void abc_preprocess(ABCHANDLE *h, ABCMACRO *m) a = m->subst[j]; if( a > 'g' && islower(a) ) { b = a - 'n'; - a = "CDEFGABCDEFGABcdefgabcdefgab"[i+b+7]; + a = "CDEFGABCDEFGABcdefgabcdefgabcdefgab"[i+b+7]; *p++ = a; if( i+b < 0 ) *p++ = ','; @@ -2290,12 +2301,12 @@ static int abc_parse_decorations(ABCHANDLE *h, ABCTRACK *tp, const char *p) if( !strncmp(p,"sfz",3) ) vol = 100; if( *p == 'p' ) { vol = 60; - while( *p++ == 'p' ) vol -= 15; + while( *p && *p++ == 'p' ) vol -= 15; if( vol < 1 ) vol = 1; } if( *p == 'f' ) { vol = 105; - while( *p++ == 'f' ) vol += 15; + while( *p && *p++ == 'f' ) vol += 15; if( vol > 135 ) vol = 127; // ffff if( vol > 127 ) vol = 125; // fff } @@ -2379,7 +2390,7 @@ static ABCHANDLE *ABC_Init(void) return retval; } -static void ABC_CleanupTrack(ABCTRACK *tp) +static void ABC_CleanupTrackEvents(ABCTRACK *tp) { ABCEVENT *ep, *en; if( tp ) { @@ -2408,7 +2419,8 @@ static void ABC_CleanupTracks(ABCHANDLE *handle) if(handle) { for( tp=handle->track; tp; tp = tn ) { tn=tp->next; - ABC_CleanupTrack(tp); + ABC_CleanupTrackEvents(tp); + free(tp); } handle->track = NULL; } @@ -3391,6 +3403,7 @@ static int abc_partpat_to_orderlist(BYTE partp[27][2], const char *abcparts, ABC if( abcparts ) { partsused = 0; for( p = abcparts; *p; p++ ) { + if (*p < 'A' || *p > 'Z') break; for( t = partp[*p - 'A'][0]; t < partp[*p - 'A'][1]; t++ ) { if( orderlen == ordersize ) { ordersize <<= 1; @@ -3572,8 +3585,8 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength) char *line, *p, *pp, ch, ch0=0; char barsig[52]; // for propagated accidental key signature within bar char *abcparts; - uint8_t partpat[27][2], *orderlist; - int orderlen; + uint8_t partpat[27][2], *orderlist = NULL; + int orderlen = 0; enum { NOWHERE, INBETWEEN, INHEAD, INBODY, INSKIPFORX, INSKIPFORQUOTE } abcstate; ABCEVENT_JUMPTYPE j; ABCEVENT_X_EFFECT abceffect; @@ -3663,8 +3676,6 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength) abc_init_partpat(partpat); abc_MIDI_beat(h, ""); // reset beat array abc_MIDI_beatstring(h, ""); // reset beatstring - orderlist = NULL; - orderlen = 0; mmsp = 1; mmstack[0] = mmfile; mmfseek(mmfile,0,SEEK_SET); @@ -3687,7 +3698,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength) while( mmsp > 0 ) { mmsp--; while((line=abc_gets(h, mmstack[mmsp]))) { - char blankline[3] = "%%"; + char blankline[3] = "% "; for( p=line; isspace(*p); p++ ) ; switch(abcstate) { case INSKIPFORX: @@ -3800,7 +3811,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength) sprintf(barsig, "%s%s", sig[abckey], sig[abckey]); // reset the key signature p = abc_skip_word(p+2); h->ktrans = abc_transpose(p); - *p = '%'; // force skip rest of line + p = blankline; // force skip rest of line if( snotelen == 0 ) { // calculate default notelen from meter M: if( mnotediv == 0 ) mnotediv = mnotelen = 1; // do'nt get nuked snotelen = 100 * mnotelen / mnotediv; @@ -3893,7 +3904,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength) sprintf(barsig, "%s%s", sig[abckey], sig[abckey]); // reset the key signature p = abc_skip_word(p+2); h->ktrans = abc_transpose(p); - *p = '%'; // make me skip the rest of the line.... + p = blankline; // make me skip the rest of the line.... } if( !strncmp(p,"L:",2) ) { sscanf(p+2," %d / %d", &snotelen, &snotediv); @@ -3934,7 +3945,8 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength) char *pm = p; if (mmstack[mmsp]->pos < dwMemLength) { pm = abc_continuated(h, mmstack[mmsp], p); - abc_new_macro(h, pm+2); + if (pm+2) + abc_new_macro(h, pm+2); } if( pm != p ) { free(pm); @@ -4060,7 +4072,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength) // plough thru the songline gathering mos.... ch0 = ' '; pp = 0; - while( (ch = *p++) ) { + while( *p && (ch = *p++) ) { if( !pp && isalpha(ch) && *p != ':' ) { // maybe a macro for( mp=h->umacro; mp; mp=mp->next ) { if( ch == mp->name[0] ) { @@ -4156,7 +4168,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength) break; } if( *p && strchr("abcdefgABCDEFG^_=",*p) ) { - int cnl[8],cnd[8],vnl,nl0=0,nd0=0,barticks; // for chords with notes of varying length + int cnl[8]={},cnd[8]={},vnl,nl0=0,nd0=0,barticks; // for chords with notes of varying length barticks = notelen_notediv_to_ticks(h->speed,1,mnotediv); if (barticks == 0) barticks = 1; abcchord = 0; @@ -4164,7 +4176,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength) h->tp = abc_check_track(h, h->tp); abc_track_clear_tiedvpos(h); abcbeatvol = abc_beat_vol(h, abcvol, (h->tracktime - bartime)/barticks); - while( (ch=*p++) && (ch != ']') ) { + while( *p && (ch=*p++) && (ch != ']') ) { h->tp = abc_locate_track(h, h->tp->v, abcchord? abcchord+DRONEPOS2: 0); p += abc_add_noteon(h, ch, p, h->tracktime, barsig, abcbeatvol, abceffect, abceffoper); p += abc_notelen(p, ¬elen, ¬ediv); @@ -4332,7 +4344,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength) int barticks = notelen_notediv_to_ticks(h->speed,1,mnotediv); if (barticks == 0) barticks = 1; abcbeatvol = abc_beat_vol(h, abcvol, (h->tracktime - bartime)/barticks); - while( (ch=*p++) && (ch != '}') ) { + while( *p && (ch=*p++) && (ch != '}') ) { p += abc_add_noteon(h, ch, p, h->tracktime+abcgrace, barsig, abcbeatvol, none, 0); p += abc_notelen(p, ¬elen, ¬ediv); if( *p=='-' ) { @@ -4418,7 +4430,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength) if( h->tp == h->tpc ) abc_add_chord(p, h, h->tpc, h->tracktime); // only do chords for one voice } abcto = 0; - while( (ch=*p++) && (ch != '"') ) { + while( *p && (ch=*p++) && (ch != '"') ) { if( !strncasecmp(p,"fade",4) && h->track && h->track->slidevol > -2 ) abc_globalslide(h, h->tracktime, -2); // set volumeslide to fade away... if( !strncasecmp(p,"to coda",7) ) { @@ -4627,7 +4639,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength) else { h->tp = abc_check_track(h, h->tp); abcvol = abc_parse_decorations(h, h->tp, p); - while( (ch=*p++) && (ch != '+') ) + while( *p && (ch=*p++) && (ch != '+') ) ; } break; @@ -4760,8 +4772,8 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength) } ABC_CleanupMacros(h); // we dont need them anymore if( !h->track ) { - char buf[10]; - sprintf(buf,"%u",abcxnumber); + char buf[11]; + sprintf(buf,"%u", abcxnumber); abc_message("abc X:%s has no body", buf); h->track = abc_check_track(h, h->track); // for sanity... } diff --git a/src/load_amf.cpp b/src/load_amf.cpp index c560a294..89876af9 100644 --- a/src/load_amf.cpp +++ b/src/load_amf.cpp @@ -310,6 +310,7 @@ BOOL CSoundFile::ReadAMF(LPCBYTE lpStream, const DWORD dwMemLength) // Setup sequence list for (UINT iOrd=0; iOrd dwMemLength) return TRUE; Order[iOrd] = 0xFF; if (iOrd < pfh->numorders) { @@ -317,8 +318,12 @@ BOOL CSoundFile::ReadAMF(LPCBYTE lpStream, const DWORD dwMemLength) PatternSize[iOrd] = 64; if (pfh->version >= 14) { + if (dwMemPos + m_nChannels * sizeof(USHORT) + 2 > dwMemLength) return FALSE; PatternSize[iOrd] = bswapLE16(*(USHORT *)(lpStream+dwMemPos)); dwMemPos += 2; + } else + { + if (dwMemPos + m_nChannels * sizeof(USHORT) > dwMemLength) return FALSE; } ptracks[iOrd] = (USHORT *)(lpStream+dwMemPos); dwMemPos += m_nChannels * sizeof(USHORT); diff --git a/src/load_ams.cpp b/src/load_ams.cpp index b05e5ab2..f2798bae 100644 --- a/src/load_ams.cpp +++ b/src/load_ams.cpp @@ -41,15 +41,16 @@ typedef struct AMSSAMPLEHEADER #pragma pack() +static BOOL AMSUnpackCheck(const BYTE *lpStream, DWORD dwMemLength, MODINSTRUMENT *ins); BOOL CSoundFile::ReadAMS(LPCBYTE lpStream, DWORD dwMemLength) //----------------------------------------------------------- { BYTE pkinf[MAX_SAMPLES]; - AMSFILEHEADER *pfh = (AMSFILEHEADER *)lpStream; + const AMSFILEHEADER *pfh = (AMSFILEHEADER *)lpStream; DWORD dwMemPos; UINT tmp, tmp2; - + if ((!lpStream) || (dwMemLength < 1024)) return FALSE; if ((pfh->verhi != 0x01) || (strncmp(pfh->szHeader, "Extreme", 7)) || (!pfh->patterns) || (!pfh->orders) || (!pfh->samples) || (pfh->samples >= MAX_SAMPLES) @@ -65,7 +66,7 @@ BOOL CSoundFile::ReadAMS(LPCBYTE lpStream, DWORD dwMemLength) m_nSamples = pfh->samples; for (UINT nSmp=1; nSmp<=m_nSamples; nSmp++, dwMemPos += sizeof(AMSSAMPLEHEADER)) { - AMSSAMPLEHEADER *psh = (AMSSAMPLEHEADER *)(lpStream + dwMemPos); + const AMSSAMPLEHEADER *psh = (AMSSAMPLEHEADER *)(lpStream + dwMemPos); MODINSTRUMENT *pins = &Ins[nSmp]; pins->nLength = psh->length; pins->nLoopStart = psh->loopstart; @@ -117,9 +118,10 @@ BOOL CSoundFile::ReadAMS(LPCBYTE lpStream, DWORD dwMemLength) dwMemPos += tmp; } // Read Song Comments + if (dwMemPos + 2 > dwMemLength) return TRUE; tmp = *((WORD *)(lpStream+dwMemPos)); dwMemPos += 2; - if (dwMemPos + tmp >= dwMemLength) return TRUE; + if (tmp >= dwMemLength || dwMemPos > dwMemLength - tmp) return TRUE; if (tmp) { m_lpszSongComments = new char[tmp+1]; // changed from CHAR @@ -129,6 +131,7 @@ BOOL CSoundFile::ReadAMS(LPCBYTE lpStream, DWORD dwMemLength) dwMemPos += tmp; } // Read Order List + if (2*pfh->orders >= dwMemLength || dwMemPos > dwMemLength - 2*pfh->orders) return TRUE; for (UINT iOrd=0; iOrdorders; iOrd++, dwMemPos += 2) { UINT n = *((WORD *)(lpStream+dwMemPos)); @@ -140,7 +143,7 @@ BOOL CSoundFile::ReadAMS(LPCBYTE lpStream, DWORD dwMemLength) if (dwMemPos + 4 >= dwMemLength) return TRUE; UINT len = *((DWORD *)(lpStream + dwMemPos)); dwMemPos += 4; - if ((len >= dwMemLength) || (dwMemPos + len > dwMemLength)) return TRUE; + if ((len >= dwMemLength) || (dwMemPos > dwMemLength - len)) return TRUE; PatternSize[iPat] = 64; MODCOMMAND *m = AllocatePattern(PatternSize[iPat], m_nChannels); if (!m) return TRUE; @@ -156,6 +159,7 @@ BOOL CSoundFile::ReadAMS(LPCBYTE lpStream, DWORD dwMemLength) // Note+Instr if (!(b0 & 0x40)) { + if (i+1 > len) break; b2 = p[i++]; if (ch < m_nChannels) { @@ -164,6 +168,7 @@ BOOL CSoundFile::ReadAMS(LPCBYTE lpStream, DWORD dwMemLength) } if (b1 & 0x80) { + if (i+1 > len) break; b0 |= 0x40; b1 = p[i++]; } @@ -181,6 +186,7 @@ BOOL CSoundFile::ReadAMS(LPCBYTE lpStream, DWORD dwMemLength) } } else { + if (i+1 > len) break; b2 = p[i++]; if (ch < m_nChannels) { @@ -223,6 +229,7 @@ BOOL CSoundFile::ReadAMS(LPCBYTE lpStream, DWORD dwMemLength) } if (b1 & 0x80) { + if (i+1 > len) break; b1 = p[i++]; if (i <= len) goto anothercommand; } @@ -240,7 +247,8 @@ BOOL CSoundFile::ReadAMS(LPCBYTE lpStream, DWORD dwMemLength) { if (dwMemPos >= dwMemLength - 9) return TRUE; UINT flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_AMS16 : RS_AMS8; - dwMemPos += ReadSample(&Ins[iSmp], flags, (LPSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos); + if (!AMSUnpackCheck(lpStream+dwMemPos, dwMemLength-dwMemPos, &Ins[iSmp])) break; + dwMemPos += ReadSample(&Ins[iSmp], flags, (LPCSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos); } return TRUE; } @@ -307,11 +315,12 @@ typedef struct AMS2SAMPLE #pragma pack() + BOOL CSoundFile::ReadAMS2(LPCBYTE lpStream, DWORD dwMemLength) //------------------------------------------------------------ { const AMS2FILEHEADER *pfh = (AMS2FILEHEADER *)lpStream; - AMS2SONGHEADER *psh; + const AMS2SONGHEADER *psh; DWORD dwMemPos; BYTE smpmap[16]; BYTE packedsamples[MAX_SAMPLES]; @@ -337,19 +346,23 @@ BOOL CSoundFile::ReadAMS2(LPCBYTE lpStream, DWORD dwMemLength) if (psh->flags & 0x40) m_dwSongFlags |= SONG_LINEARSLIDES; for (UINT nIns=1; nIns<=m_nInstruments; nIns++) { + if (dwMemPos >= dwMemLength) return TRUE; UINT insnamelen = lpStream[dwMemPos]; - CHAR *pinsname = (CHAR *)(lpStream+dwMemPos+1); + const CHAR *pinsname = (CHAR *)(lpStream+dwMemPos+1); dwMemPos += insnamelen + 1; - AMS2INSTRUMENT *pins = (AMS2INSTRUMENT *)(lpStream + dwMemPos); + const AMS2INSTRUMENT *pins = (AMS2INSTRUMENT *)(lpStream + dwMemPos); dwMemPos += sizeof(AMS2INSTRUMENT); - if (dwMemPos + 1024 >= dwMemLength) return TRUE; - AMS2ENVELOPE *volenv, *panenv, *pitchenv; + const AMS2ENVELOPE *volenv, *panenv, *pitchenv; + if (dwMemPos + sizeof(AMS2ENVELOPE) > dwMemLength) return TRUE; volenv = (AMS2ENVELOPE *)(lpStream+dwMemPos); dwMemPos += 5 + volenv->points*3; + if (dwMemPos + sizeof(AMS2ENVELOPE) > dwMemLength) return TRUE; panenv = (AMS2ENVELOPE *)(lpStream+dwMemPos); dwMemPos += 5 + panenv->points*3; + if (dwMemPos + sizeof(AMS2ENVELOPE) > dwMemLength) return TRUE; pitchenv = (AMS2ENVELOPE *)(lpStream+dwMemPos); dwMemPos += 5 + pitchenv->points*3; + if (dwMemPos >= dwMemLength) return TRUE; INSTRUMENTHEADER *penv = new INSTRUMENTHEADER; if (!penv) return TRUE; memset(smpmap, 0, sizeof(smpmap)); @@ -389,6 +402,7 @@ BOOL CSoundFile::ReadAMS2(LPCBYTE lpStream, DWORD dwMemLength) penv->VolPoints[i] = (WORD)pos; } } + if (dwMemPos + 5 > dwMemLength) return TRUE; penv->nFadeOut = (((lpStream[dwMemPos+2] & 0x0F) << 8) | (lpStream[dwMemPos+1])) << 3; UINT envflags = lpStream[dwMemPos+3]; if (envflags & 0x01) penv->dwFlags |= ENV_VOLLOOP; @@ -398,16 +412,19 @@ BOOL CSoundFile::ReadAMS2(LPCBYTE lpStream, DWORD dwMemLength) // Read Samples for (UINT ismp=0; ismpsamples; ismp++) { + if (dwMemPos + 1 > dwMemLength) return TRUE; MODINSTRUMENT *psmp = ((ismp < 16) && (smpmap[ismp])) ? &Ins[smpmap[ismp]] : NULL; UINT smpnamelen = lpStream[dwMemPos]; + if (dwMemPos + smpnamelen + 1 > dwMemLength) return TRUE; if ((psmp) && (smpnamelen) && (smpnamelen <= 22)) { memcpy(m_szNames[smpmap[ismp]], lpStream+dwMemPos+1, smpnamelen); } dwMemPos += smpnamelen + 1; + if (dwMemPos + sizeof(AMS2SAMPLE) > dwMemLength) return TRUE; if (psmp) { - AMS2SAMPLE *pams = (AMS2SAMPLE *)(lpStream+dwMemPos); + const AMS2SAMPLE *pams = (AMS2SAMPLE *)(lpStream+dwMemPos); psmp->nGlobalVol = 64; psmp->nPan = 128; psmp->nLength = pams->length; @@ -547,16 +564,40 @@ BOOL CSoundFile::ReadAMS2(LPCBYTE lpStream, DWORD dwMemLength) if (packedsamples[iSmp] & 0x03) { flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_AMS16 : RS_AMS8; + if (!AMSUnpackCheck(lpStream+dwMemPos, dwMemLength-dwMemPos, &Ins[iSmp])) break; } else { flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S; } - dwMemPos += ReadSample(&Ins[iSmp], flags, (LPSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos); + dwMemPos += ReadSample(&Ins[iSmp], flags, (LPCSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos); } return TRUE; } +// Precheck AMS packed sample size to determine whether or not it could fit the actual size. +static BOOL AMSUnpackCheck(const BYTE *lpStream, DWORD dwMemLength, MODINSTRUMENT *ins) +// ----------------------------------------------------------------------------------- +{ + if (dwMemLength < 9) return FALSE; + DWORD packedbytes = *((DWORD *)(lpStream + 4)); + + DWORD samplebytes = ins->nLength; + if (samplebytes > MAX_SAMPLE_LENGTH) samplebytes = MAX_SAMPLE_LENGTH; + if (ins->uFlags & CHN_16BIT) samplebytes *= 2; + + // RLE can pack a run of up to 255 bytes into 3 bytes. + DWORD packedmin = (samplebytes * 3) >> 8; + if (packedbytes < packedmin) + { + samplebytes = packedbytes * (255 / 3) + 2; + ins->nLength = samplebytes; + if (ins->uFlags & CHN_16BIT) ins->nLength >>= 1; + } + + return TRUE; +} + ///////////////////////////////////////////////////////////////////// // AMS Sample unpacking @@ -564,7 +605,7 @@ void AMSUnpack(const char *psrc, UINT inputlen, char *pdest, UINT dmax, char pac { UINT tmplen = dmax; signed char *amstmp = new signed char[tmplen]; - + if (!amstmp) return; // Unpack Loop { @@ -575,9 +616,11 @@ void AMSUnpack(const char *psrc, UINT inputlen, char *pdest, UINT dmax, char pac signed char ch = psrc[i++]; if (ch == packcharacter) { + if (i >= inputlen) break; BYTE ch2 = psrc[i++]; if (ch2) { + if (i >= inputlen) break; ch = psrc[i++]; while (ch2--) { @@ -587,6 +630,12 @@ void AMSUnpack(const char *psrc, UINT inputlen, char *pdest, UINT dmax, char pac } else p[j++] = packcharacter; } else p[j++] = ch; } + if (j < tmplen) + { + // Truncated or invalid; don't try to unpack this. + delete[] amstmp; + return; + } } // Bit Unpack Loop { diff --git a/src/load_dbm.cpp b/src/load_dbm.cpp index 9aff94b8..286dcb42 100644 --- a/src/load_dbm.cpp +++ b/src/load_dbm.cpp @@ -136,6 +136,9 @@ BOOL CSoundFile::ReadDBM(const BYTE *lpStream, DWORD dwMemLength) // Instruments if (chunk_id == bswapLE32(DBM_ID_INST)) { + // Skip duplicate chunks. + if (m_nInstruments) continue; + if (nInstruments >= MAX_INSTRUMENTS) nInstruments = MAX_INSTRUMENTS-1; for (UINT iIns=0; iIns dwMemPos) break; pph = (DBMPATTERN *)(lpStream+chunk_pos); pksize = bswapBE32(pph->packedsize); diff --git a/src/load_dmf.cpp b/src/load_dmf.cpp index 7bfca226..9eba77df 100644 --- a/src/load_dmf.cpp +++ b/src/load_dmf.cpp @@ -87,11 +87,12 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength) //--------------------------------------------------------------- { const DMFHEADER *pfh = (DMFHEADER *)lpStream; - DMFINFO *psi; - DMFSEQU *sequ; + const DMFINFO *psi; + const DMFPATT *patt; + const DMFSEQU *sequ; DWORD dwMemPos; BYTE infobyte[32]; - BYTE smplflags[MAX_SAMPLES], hasSMPI = 0; + BYTE smplflags[MAX_SAMPLES], hasSMPI = 0, hasSMPD = 0; if ((!lpStream) || (dwMemLength < 1024)) return FALSE; if ((pfh->id != 0x464d4444) || (!pfh->version) || (pfh->version & 0xF0)) return FALSE; @@ -115,7 +116,7 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength) case 0x47534d43: psi = (DMFINFO *)(lpStream+dwMemPos); if (id == 0x47534d43) dwMemPos++; - if ((psi->infosize > dwMemLength) || (psi->infosize + dwMemPos + 8 > dwMemLength)) goto dmfexit; + if ((psi->infosize > dwMemLength) || (dwMemPos + 8 > dwMemLength - psi->infosize)) goto dmfexit; if ((psi->infosize >= 8) && (!m_lpszSongComments)) { m_lpszSongComments = new char[psi->infosize]; // changed from CHAR @@ -138,9 +139,10 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength) // "SEQU" case 0x55514553: sequ = (DMFSEQU *)(lpStream+dwMemPos); - if ((sequ->seqsize >= dwMemLength) || (dwMemPos + sequ->seqsize + 12 > dwMemLength)) goto dmfexit; + if ((sequ->seqsize >= dwMemLength) || (dwMemPos + 8 > dwMemLength - sequ->seqsize)) goto dmfexit; + if (sequ->seqsize >= 4) { - UINT nseq = sequ->seqsize >> 1; + UINT nseq = (sequ->seqsize - 4) >> 1; if (nseq >= MAX_ORDERS-1) nseq = MAX_ORDERS-1; if (sequ->loopstart < nseq) m_nRestartPos = sequ->loopstart; for (UINT i=0; isequ[i]; @@ -150,12 +152,12 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength) // "PATT" case 0x54544150: - if (!m_nChannels) + patt = (DMFPATT *)(lpStream+dwMemPos); + if ((patt->patsize >= dwMemLength) || (dwMemPos + 8 > dwMemLength - patt->patsize)) goto dmfexit; + if (patt->patsize >= 4 && !m_nChannels) { - DMFPATT *patt = (DMFPATT *)(lpStream+dwMemPos); UINT numpat; DWORD dwPos = dwMemPos + 11; - if ((patt->patsize >= dwMemLength) || (dwMemPos + patt->patsize + 8 > dwMemLength)) goto dmfexit; numpat = patt->numpat; if (numpat > MAX_PATTERNS) numpat = MAX_PATTERNS; m_nChannels = patt->tracks; @@ -164,7 +166,8 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength) if (m_nChannels < 4) m_nChannels = 4; for (UINT npat=0; npat= dwMemLength) break; #ifdef DMFLOG Log("Pattern #%d: %d tracks, %d rows\n", npat, pt->tracks, pt->ticks); #endif @@ -174,7 +177,7 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength) if (ticks > 256) ticks = 256; if (ticks < 16) ticks = 16; dwPos += 8; - if ((pt->jmpsize >= dwMemLength) || (dwPos + pt->jmpsize + 4 >= dwMemLength)) break; + if ((pt->jmpsize >= dwMemLength) || (dwPos + 4 > dwMemLength - pt->jmpsize)) break; PatternSize[npat] = (WORD)ticks; MODCOMMAND *m = AllocatePattern(PatternSize[npat], m_nChannels); if (!m) goto dmfexit; @@ -193,6 +196,7 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength) // Parse track global effects if (!glbinfobyte) { + if (d+1 > dwPos) break; BYTE info = lpStream[d++]; BYTE infoval = 0; if ((info & 0x80) && (d < dwPos)) glbinfobyte = lpStream[d++]; @@ -214,17 +218,24 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength) // Parse channels for (UINT i=0; i dwPos) break; MODCOMMAND cmd = {0,0,0,0,0,0}; BYTE info = lpStream[d++]; - if (info & 0x80) infobyte[i] = lpStream[d++]; + if (info & 0x80) + { + if (d+1 > dwPos) break; + infobyte[i] = lpStream[d++]; + } // Instrument if (info & 0x40) { + if (d+1 > dwPos) break; cmd.instr = lpStream[d++]; } // Note if (info & 0x20) { + if (d+1 > dwPos) break; cmd.note = lpStream[d++]; if ((cmd.note) && (cmd.note < 0xfe)) cmd.note &= 0x7f; if ((cmd.note) && (cmd.note < 128)) cmd.note += 24; @@ -232,12 +243,15 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength) // Volume if (info & 0x10) { + if (d+1 > dwPos) break; cmd.volcmd = VOLCMD_VOLUME; cmd.vol = (lpStream[d++]+3)>>2; } // Effect 1 if (info & 0x08) { + if (d+2 > dwPos) break; + BYTE efx = lpStream[d++]; BYTE eval = lpStream[d++]; switch(efx) @@ -259,6 +273,8 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength) // Effect 2 if (info & 0x04) { + if (d+2 > dwPos) break; + BYTE efx = lpStream[d++]; BYTE eval = lpStream[d++]; switch(efx) @@ -288,6 +304,8 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength) // Effect 3 if (info & 0x02) { + if (d+2 > dwPos) break; + BYTE efx = lpStream[d++]; BYTE eval = lpStream[d++]; switch(efx) @@ -371,22 +389,24 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength) #endif if (dwPos + 8 >= dwMemLength) break; } - dwMemPos += patt->patsize + 8; } + dwMemPos += patt->patsize + 8; break; // "SMPI": Sample Info case 0x49504d53: { hasSMPI = 1; - DMFSMPI *pds = (DMFSMPI *)(lpStream+dwMemPos); - if (pds->size <= dwMemLength - dwMemPos) + const DMFSMPI *pds = (DMFSMPI *)(lpStream+dwMemPos); + if ((pds->size >= dwMemLength) || (dwMemPos + 8 > dwMemLength - pds->size)) goto dmfexit; + if (pds->size >= 1) { DWORD dwPos = dwMemPos + 9; m_nSamples = pds->samples; if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1; for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++) { + if (dwPos >= dwMemPos + pds->size + 8) break; UINT namelen = lpStream[dwPos]; smplflags[iSmp] = 0; if (dwPos+namelen+1+sizeof(DMFSAMPLE) > dwMemPos+pds->size+8) break; @@ -397,7 +417,7 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength) m_szNames[iSmp][rlen] = 0; } dwPos += namelen + 1; - DMFSAMPLE *psh = (DMFSAMPLE *)(lpStream+dwPos); + const DMFSAMPLE *psh = (DMFSAMPLE *)(lpStream+dwPos); MODINSTRUMENT *psmp = &Ins[iSmp]; psmp->nLength = psh->len; psmp->nLoopStart = psh->loopstart; @@ -424,7 +444,7 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength) { DWORD dwPos = dwMemPos + 8; UINT ismpd = 0; - for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++) + for (UINT iSmp=1; iSmp<=m_nSamples && !hasSMPD; iSmp++) { ismpd++; DWORD pksize; @@ -457,6 +477,7 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength) } dwPos += pksize; } + hasSMPD = 1; dwMemPos = dwPos; } break; @@ -519,8 +540,8 @@ BYTE DMFReadBits(DMF_HTREE *tree, UINT nbits) { tree->bitnum--; } else - { - tree->bitbuf = (tree->ibuf < tree->ibufmax) ? *(tree->ibuf++) : 0; + if (tree->ibuf < tree->ibufmax) { + tree->bitbuf = *(tree->ibuf++); tree->bitnum = 7; } if (tree->bitbuf & 1) x |= bitv; @@ -575,14 +596,24 @@ int DMFUnpack(LPBYTE psample, LPBYTE ibuf, LPBYTE ibufmax, UINT maxlen) DMF_HTREE tree; UINT actnode; BYTE value, sign, delta = 0; - + memset(&tree, 0, sizeof(tree)); tree.ibuf = ibuf; tree.ibufmax = ibufmax; DMFNewNode(&tree); value = 0; + + if (tree.ibuf >= ibufmax) return tree.ibuf - ibuf; + for (UINT i=0; i= tree.ibufmax) && (!tree.bitnum)) + { + #ifdef DMFLOG + Log("DMFUnpack: unexpected EOF at output byte %d / %d\n", i, maxlen); + #endif + break; + } actnode = 0; sign = DMFReadBits(&tree, 1); do diff --git a/src/load_far.cpp b/src/load_far.cpp index b070a243..c223480a 100644 --- a/src/load_far.cpp +++ b/src/load_far.cpp @@ -109,7 +109,7 @@ BOOL CSoundFile::ReadFAR(const BYTE *lpStream, DWORD dwMemLength) Order[iorder] = (iorder <= pmh2->snglen) ? pmh2->orders[iorder] : 0xFF; } m_nRestartPos = pmh2->loopto; - // Reading Patterns + // Reading Patterns dwMemPos += headerlen - (869 + stlen); if (dwMemPos >= dwMemLength) return TRUE; @@ -125,6 +125,7 @@ BOOL CSoundFile::ReadFAR(const BYTE *lpStream, DWORD dwMemLength) continue; } if (dwMemPos + patlen >= dwMemLength) return TRUE; + UINT max = (patlen - 2) & ~3; UINT rows = (patlen - 2) >> 6; if (!rows) { @@ -133,13 +134,12 @@ BOOL CSoundFile::ReadFAR(const BYTE *lpStream, DWORD dwMemLength) } if (rows > 256) rows = 256; if (rows < 16) rows = 16; + if (max > rows*16*4) max = rows*16*4; PatternSize[ipat] = rows; if ((Patterns[ipat] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE; MODCOMMAND *m = Patterns[ipat]; UINT patbrk = lpStream[dwMemPos]; const BYTE *p = lpStream + dwMemPos + 2; - UINT max = rows*16*4; - if (max > patlen-2) max = patlen-2; for (UINT len=0; len= ibufend) + return 0; + bitbuf = *ibuf++; bitnum = 8; } @@ -1218,12 +1221,14 @@ void ITUnpack8Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwM { signed char *pDst = pSample; LPBYTE pSrc = lpMemFile; + LPBYTE pStop = lpMemFile + dwMemLength; DWORD wHdr = 0; DWORD wCount = 0; DWORD bitbuf = 0; UINT bitnum = 0; BYTE bLeft = 0, bTemp = 0, bTemp2 = 0; + while (dwLen) { if (!wCount) @@ -1235,19 +1240,20 @@ void ITUnpack8Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwM bTemp = bTemp2 = 0; bitbuf = bitnum = 0; } + DWORD d = wCount; if (d > dwLen) d = dwLen; // Unpacking DWORD dwPos = 0; do { - WORD wBits = (WORD)ITReadBits(bitbuf, bitnum, pSrc, bLeft); + WORD wBits = (WORD)ITReadBits(bitbuf, bitnum, pSrc, pStop, bLeft); if (bLeft < 7) { DWORD i = 1 << (bLeft-1); DWORD j = wBits & 0xFFFF; if (i != j) goto UnpackByte; - wBits = (WORD)(ITReadBits(bitbuf, bitnum, pSrc, 3) + 1) & 0xFF; + wBits = (WORD)(ITReadBits(bitbuf, bitnum, pSrc, pStop, 3) + 1) & 0xFF; bLeft = ((BYTE)wBits < bLeft) ? (BYTE)wBits : (BYTE)((wBits+1) & 0xFF); goto Next; } @@ -1285,7 +1291,7 @@ void ITUnpack8Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwM SkipByte: dwPos++; Next: - if (pSrc >= lpMemFile+dwMemLength+1) return; + if (pSrc >= pStop + 1) return; } while (dwPos < d); // Move On wCount -= d; @@ -1300,6 +1306,7 @@ void ITUnpack16Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dw { signed short *pDst = (signed short *)pSample; LPBYTE pSrc = lpMemFile; + LPBYTE pStop = lpMemFile + dwMemLength; DWORD wHdr = 0; DWORD wCount = 0; DWORD bitbuf = 0; @@ -1324,13 +1331,13 @@ void ITUnpack16Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dw DWORD dwPos = 0; do { - DWORD dwBits = ITReadBits(bitbuf, bitnum, pSrc, bLeft); + DWORD dwBits = ITReadBits(bitbuf, bitnum, pSrc, pStop, bLeft); if (bLeft < 7) { DWORD i = 1 << (bLeft-1); DWORD j = dwBits; if (i != j) goto UnpackByte; - dwBits = ITReadBits(bitbuf, bitnum, pSrc, 4) + 1; + dwBits = ITReadBits(bitbuf, bitnum, pSrc, pStop, 4) + 1; bLeft = ((BYTE)(dwBits & 0xFF) < bLeft) ? (BYTE)(dwBits & 0xFF) : (BYTE)((dwBits+1) & 0xFF); goto Next; } @@ -1368,13 +1375,13 @@ void ITUnpack16Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dw SkipByte: dwPos++; Next: - if (pSrc >= lpMemFile+dwMemLength+1) return; + if (pSrc >= pStop + 1) return; } while (dwPos < d); // Move On wCount -= d; dwLen -= d; pDst += d; - if (pSrc >= lpMemFile+dwMemLength) break; + if (pSrc >= pStop) break; } } diff --git a/src/load_mdl.cpp b/src/load_mdl.cpp index 8f2724fc..ac78aa67 100644 --- a/src/load_mdl.cpp +++ b/src/load_mdl.cpp @@ -125,17 +125,17 @@ void UnpackMDLTrack(MODCOMMAND *pat, UINT nChannels, UINT nRows, UINT nTrack, co case 0x03: { - cmd.note = (xx & 0x01) ? lpTracks[pos++] : 0; - cmd.instr = (xx & 0x02) ? lpTracks[pos++] : 0; + cmd.note = (xx & 0x01) ? (pos < len ? lpTracks[pos++] : 0) : 0; + cmd.instr = (xx & 0x02) ? (pos < len ? lpTracks[pos++] : 0) : 0; cmd.volcmd = cmd.vol = 0; cmd.command = cmd.param = 0; if ((cmd.note < NOTE_MAX-12) && (cmd.note)) cmd.note += 12; - UINT volume = (xx & 0x04) ? lpTracks[pos++] : 0; - UINT commands = (xx & 0x08) ? lpTracks[pos++] : 0; + UINT volume = (xx & 0x04) ? (pos < len ? lpTracks[pos++] : 0) : 0; + UINT commands = (xx & 0x08) ? (pos < len ? lpTracks[pos++] : 0) : 0; UINT command1 = commands & 0x0F; UINT command2 = commands & 0xF0; - UINT param1 = (xx & 0x10) ? lpTracks[pos++] : 0; - UINT param2 = (xx & 0x20) ? lpTracks[pos++] : 0; + UINT param1 = (xx & 0x10) ? (pos < len ? lpTracks[pos++] : 0) : 0; + UINT param2 = (xx & 0x20) ? (pos < len ? lpTracks[pos++] : 0) : 0; if ((command1 == 0x0E) && ((param1 & 0xF0) == 0xF0) && (!command2)) { param1 = ((param1 & 0x0F) << 8) | param2; @@ -212,11 +212,13 @@ BOOL CSoundFile::ReadMDL(const BYTE *lpStream, DWORD dwMemLength) { // IN: infoblock case 0x4E49: + if (blocklen < sizeof(MDLINFOBLOCK)) break; pmib = (const MDLINFOBLOCK *)(lpStream+dwMemPos); memcpy(m_szNames[0], pmib->songname, 32); m_szNames[0][31] = 0; norders = pmib->norders; if (norders > MAX_ORDERS) norders = MAX_ORDERS; + if (blocklen < sizeof(MDLINFOBLOCK) + norders - sizeof(pmib->seq)) return FALSE; m_nRestartPos = pmib->repeatpos; m_nDefaultGlobalVolume = pmib->globalvol; m_nDefaultTempo = pmib->tempo; @@ -278,6 +280,7 @@ BOOL CSoundFile::ReadMDL(const BYTE *lpStream, DWORD dwMemLength) break; // TR: Track Data case 0x5254: + if (blocklen < 2) break; if (dwTrackPos) break; pp = lpStream + dwMemPos; ntracks = pp[0] | (pp[1] << 8); @@ -287,6 +290,8 @@ BOOL CSoundFile::ReadMDL(const BYTE *lpStream, DWORD dwMemLength) case 0x4949: ninstruments = lpStream[dwMemPos]; dwPos = dwMemPos+1; + if (blocklen < sizeof(INSTRUMENTHEADER)*ninstruments + 1) break; + for (i=0; iname, lpStream+dwPos+2, 32); + if (dwPos < dwMemLength - 34) + memcpy(penv->name, lpStream+dwPos+2, 32); penv->nGlobalVol = 64; penv->nPPC = 5*12; + if (34 + 14u*lpStream[dwPos+1] > dwMemLength - dwPos) break; for (j=0; j= dwMemLength - 12) break; while ((note < (UINT)(ps[1]+12)) && (note < NOTE_MAX)) { penv->NoteMap[note] = note+1; @@ -337,6 +345,7 @@ BOOL CSoundFile::ReadMDL(const BYTE *lpStream, DWORD dwMemLength) } } dwPos += 34 + 14*lpStream[dwPos+1]; + if (dwPos > dwMemLength - 2) break; } for (j=1; j<=m_nInstruments; j++) if (!Headers[j]) { @@ -346,18 +355,18 @@ BOOL CSoundFile::ReadMDL(const BYTE *lpStream, DWORD dwMemLength) break; // VE: Volume Envelope case 0x4556: - if ((nvolenv = lpStream[dwMemPos]) == 0) break; - if (dwMemPos + nvolenv*32 + 1 <= dwMemLength) pvolenv = lpStream + dwMemPos + 1; + if (nvolenv || (nvolenv = lpStream[dwMemPos]) == 0) break; + if (dwMemPos + nvolenv*33 + 1 <= dwMemLength) pvolenv = lpStream + dwMemPos + 1; break; // PE: Panning Envelope case 0x4550: - if ((npanenv = lpStream[dwMemPos]) == 0) break; - if (dwMemPos + npanenv*32 + 1 <= dwMemLength) ppanenv = lpStream + dwMemPos + 1; + if (npanenv || (npanenv = lpStream[dwMemPos]) == 0) break; + if (dwMemPos + npanenv*33 + 1 <= dwMemLength) ppanenv = lpStream + dwMemPos + 1; break; // FE: Pitch Envelope case 0x4546: - if ((npitchenv = lpStream[dwMemPos]) == 0) break; - if (dwMemPos + npitchenv*32 + 1 <= dwMemLength) ppitchenv = lpStream + dwMemPos + 1; + if (npitchenv || (npitchenv = lpStream[dwMemPos]) == 0) break; + if (dwMemPos + npitchenv*33 + 1 <= dwMemLength) ppitchenv = lpStream + dwMemPos + 1; break; // IS: Sample Infoblock case 0x5349: @@ -432,22 +441,26 @@ BOOL CSoundFile::ReadMDL(const BYTE *lpStream, DWORD dwMemLength) for (UINT chn=0; chn dwMemLength - dwTrackPos ) len = 0; + if ( len > dwMemLength - (lpTracks - lpStream) ) len = 0; - UnpackMDLTrack(m, m_nChannels, PatternSize[ipat], nTrack, lpTracks, len); + UnpackMDLTrack(m, m_nChannels, PatternSize[ipat], nTrack, lpTracks, len); } } } diff --git a/src/load_med.cpp b/src/load_med.cpp index 745e2c65..e5b3076c 100644 --- a/src/load_med.cpp +++ b/src/load_med.cpp @@ -662,7 +662,7 @@ BOOL CSoundFile::ReadMed(const BYTE *lpStream, DWORD dwMemLength) } UINT pseq = 0; - if ((playseqtable) && (playseqtable < dwMemLength) && (nplayseq*4 < dwMemLength - playseqtable)) + if ((playseqtable) && (playseqtable < dwMemLength - 4) && ((nplayseq+1)*4 < dwMemLength - playseqtable)) { pseq = bswapBE32(((LPDWORD)(lpStream+playseqtable))[nplayseq]); } @@ -768,7 +768,7 @@ BOOL CSoundFile::ReadMed(const BYTE *lpStream, DWORD dwMemLength) if (trknamelen > MAX_CHANNELNAME) trknamelen = MAX_CHANNELNAME; if ((trknameofs) && (trknamelen < dwMemLength) && (trknameofs < dwMemLength - trknamelen)) { - lstrcpyn(ChnSettings[i].szName, (LPCSTR)(lpStream+trknameofs), MAX_CHANNELNAME); + lstrcpyn(ChnSettings[i].szName, (LPCSTR)(lpStream+trknameofs), trknamelen); ChnSettings[i].szName[MAX_CHANNELNAME-1] = '\0'; } } @@ -790,9 +790,11 @@ BOOL CSoundFile::ReadMed(const BYTE *lpStream, DWORD dwMemLength) if ((len > MAX_SAMPLE_LENGTH) || (dwPos + len + 6 > dwMemLength)) len = 0; UINT flags = RS_PCM8S, stype = bswapBE16(psdh->type); LPSTR psdata = (LPSTR)(lpStream + dwPos + 6); + UINT bLimit = dwMemLength - dwPos - 6; if (stype & 0x80) { psdata += (stype & 0x20) ? 14 : 6; + bLimit -= (stype & 0x20) ? 14 : 6; } else { if (stype & 0x10) @@ -807,7 +809,7 @@ BOOL CSoundFile::ReadMed(const BYTE *lpStream, DWORD dwMemLength) if (stype & 0x20) len /= 2; } Ins[iSmp+1].nLength = len; - ReadSample(&Ins[iSmp+1], flags, psdata, dwMemLength - dwPos - 6); + ReadSample(&Ins[iSmp+1], flags, psdata, bLimit); } // Reading patterns (blocks) if (wNumBlocks > MAX_PATTERNS) wNumBlocks = MAX_PATTERNS; @@ -876,9 +878,15 @@ BOOL CSoundFile::ReadMed(const BYTE *lpStream, DWORD dwMemLength) { DWORD nameofs = bswapBE32(pbi->blockname); UINT namelen = bswapBE32(pbi->blocknamelen); - if ((nameofs < dwMemLength) && (namelen < dwMemLength + nameofs)) + if ((namelen < dwMemLength) && (nameofs < dwMemLength - namelen)) { - SetPatternName(iBlk, (LPCSTR)(lpStream+nameofs)); + // SetPatternName expects a nul-terminated string. + char blockname[MAX_PATTERNNAME]; + if (namelen >= MAX_PATTERNNAME) namelen = MAX_PATTERNNAME - 1; + memcpy(blockname, lpStream + nameofs, namelen); + blockname[namelen] = '\0'; + + SetPatternName(iBlk, blockname); } } if (pbi->cmdexttable) diff --git a/src/load_mid.cpp b/src/load_mid.cpp index 5992fa64..bce944f4 100644 --- a/src/load_mid.cpp +++ b/src/load_mid.cpp @@ -105,6 +105,7 @@ typedef struct { char *mm; unsigned int sz; int pos; + int err; } MMFILE; static void mmfseek(MMFILE *mmfile, long p, int whence) @@ -130,21 +131,38 @@ static long mmftell(MMFILE *mmfile) static BYTE mmreadUBYTE(MMFILE *mmfile) { BYTE b; + if ((unsigned int)mmfile->pos >= mmfile->sz) + { + mmfile->err = EOF; + return 0; + } b = (BYTE)mmfile->mm[mmfile->pos]; mmfile->pos++; return b; } -static void mmreadUBYTES(BYTE *buf, long sz, MMFILE *mmfile) +static unsigned long mmreadUBYTES(BYTE *buf, unsigned long sz, MMFILE *mmfile) { + if ((unsigned long)mmfile->pos + sz >= mmfile->sz) + { + mmfile->err = EOF; + return 0; + } memcpy(buf, &mmfile->mm[mmfile->pos], sz); mmfile->pos += sz; + return sz; } -static void mmreadSBYTES(char *buf, long sz, MMFILE *mmfile) +static unsigned long mmreadSBYTES(char *buf, long sz, MMFILE *mmfile) { + if ((unsigned long)mmfile->pos + sz >= mmfile->sz) + { + mmfile->err = EOF; + return 0; + } memcpy(buf, &mmfile->mm[mmfile->pos], sz); mmfile->pos += sz; + return sz; } /**********************************************************************/ @@ -417,6 +435,10 @@ static MIDTRACK *mid_locate_track(MIDHANDLE *h, int mch, int pos) for( tr=h->track; tr; tr=tr->next ) { if( tr->chan == mch ) { e = tr->workevent; + if (!e) { + trunused = tr; + break; + } if( h->tracktime > e->tracktick + tmin ) { tmin = h->tracktime - e->tracktick; trunused = tr; @@ -433,6 +455,10 @@ static MIDTRACK *mid_locate_track(MIDHANDLE *h, int mch, int pos) for( tr=h->track; tr; tr=tr->next ) { if( tr->chan == mch ) { e = tr->workevent; + if (!e) { + trunused = tr; + break; + } if( h->tracktime >= e->tracktick + tmin ) { tmin = h->tracktime - e->tracktick; trunused = tr; @@ -446,6 +472,10 @@ static MIDTRACK *mid_locate_track(MIDHANDLE *h, int mch, int pos) tmin = 0; for( tr=h->track; tr; tr=tr->next ) { e = tr->workevent; + if (!e) { + trunused = tr; + break; + } if( h->tracktime >= e->tracktick + tmin ) { tmin = h->tracktime - e->tracktick; trunused = tr; @@ -708,21 +738,26 @@ static void mid_add_pitchwheel(MIDHANDLE *h, int mch, int wheel) static uint32_t mid_read_long(MIDHANDLE *h) { - BYTE buf[4]; - mmreadUBYTES(buf, 4, h->mmf); + BYTE buf[4] = {}; + if (h->mmf->pos < h->mmf->sz - 4) + mmreadUBYTES(buf, 4, h->mmf); return (buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|buf[3]; } static short int mid_read_short(MIDHANDLE *h) { - BYTE buf[2]; - mmreadUBYTES(buf, 2, h->mmf); + BYTE buf[2] = {}; + if (h->mmf->pos < h->mmf->sz - 2) + mmreadUBYTES(buf, 2, h->mmf); return (buf[0]<<8)|buf[1]; } static BYTE mid_read_byte(MIDHANDLE *h) { - return mmreadUBYTE(h->mmf); + if (h->mmf->pos < h->mmf->sz - 1) + return mmreadUBYTE(h->mmf); + else + return 0; } static int mid_read_delta(MIDHANDLE *h) @@ -750,8 +785,9 @@ BOOL CSoundFile::TestMID(const BYTE *lpStream, DWORD dwMemLength) MMFILE mm; mm.mm = (char *)lpStream; mm.sz = dwMemLength; + mm.err = 0; h.mmf = &mm; - if (h.mmf->sz < 4) return FALSE; + if (h.mmf->sz < 8) return FALSE; mmfseek(h.mmf,0,SEEK_SET); mmreadSBYTES(id, 4, h.mmf); id[4] = '\0'; @@ -767,6 +803,7 @@ static MIDHANDLE *MID_Init(void) retval->track = NULL; retval->percussion = 0; retval->debug = NULL; + retval->miditracks = 0; return retval; } @@ -791,6 +828,7 @@ static void MID_CleanupTracks(MIDHANDLE *handle) for( tp=handle->track; tp; tp = tn ) { tn=tp->next; MID_CleanupTrack(tp); + free(tp); } handle->track = NULL; } @@ -1074,7 +1112,7 @@ static void mid_notes_to_percussion(MIDTRACK *tp, ULONG adjust, ULONG tmin) } } if( ton > toff ) { - char info[32]; + char info[64]; sprintf(info,"%ld > %ld note %d", (long)ton, (long)toff, n); mid_message("drum track ends with note on (%s)", info); } @@ -1128,7 +1166,7 @@ static void mid_prog_to_notes(MIDTRACK *tp, ULONG adjust, ULONG tmin) } } if( ton > toff ) { - char info[40]; + char info[128]; sprintf(info,"channel %d, %ld > %ld note %d", tp->chan + 1, (long)ton, (long)toff, n); mid_message("melody track ends with note on (%s)", info); } @@ -1172,29 +1210,29 @@ BOOL CSoundFile::ReadMID(const BYTE *lpStream, DWORD dwMemLength) BYTE *p; while( avoid_reentry ) sleep(1); avoid_reentry = 1; - if( !TestMID(lpStream, dwMemLength) ) { - avoid_reentry = 0; - return FALSE; - } + if( !TestMID(lpStream, dwMemLength) ) goto ErrorExit; h = MID_Init(); - if( !h ) { - avoid_reentry = 0; - return FALSE; - } + if( !h ) goto ErrorExit; h->mmf = &mm; mm.mm = (char *)lpStream; mm.sz = dwMemLength; mm.pos = 0; + mm.err = 0; h->debug = getenv(ENV_MMMID_DEBUG); h->verbose = getenv(ENV_MMMID_VERBOSE); pat_resetsmp(); pat_init_patnames(); + mmfseek(h->mmf,8,SEEK_SET); - h->midiformat = mid_read_short(h); - h->miditracks = mid_read_short(h); - h->resolution = mid_read_short(h); + if (h->mmf->pos < dwMemLength - 6) { + h->midiformat = mid_read_short(h); + h->miditracks = mid_read_short(h); + h->resolution = mid_read_short(h); + if( h->midiformat == 0 ) h->miditracks = 1; + } + if (mm.err) goto ErrorCleanup; + // at this point the h->mmf is positioned at first miditrack - if( h->midiformat == 0 ) h->miditracks = 1; if( h->resolution & 0x8000 ) h->divider = ((h->resolution & 0x7f00)>>8)*(h->resolution & 0xff); else @@ -1205,11 +1243,8 @@ BOOL CSoundFile::ReadMID(const BYTE *lpStream, DWORD dwMemLength) m_nDefaultTempo = 0; h->tracktime = 0; h->speed = 6; - if (h->miditracks == 0) { - MID_Cleanup(h); - avoid_reentry = 0; - return FALSE; - } + if (h->miditracks == 0) goto ErrorCleanup; + p = (BYTE *)getenv(ENV_MMMID_SPEED); if( p && isdigit(*p) && p[0] != '0' && p[1] == '\0' ) { // transform speed @@ -1247,19 +1282,22 @@ BOOL CSoundFile::ReadMID(const BYTE *lpStream, DWORD dwMemLength) } for( t=0; t<(uint32_t)h->miditracks; t++ ) { if( h->verbose ) printf("Parsing track %d\n", t+1); - mmreadSBYTES(buf,4,h->mmf); + if (h->mmf->pos < dwMemLength - 4) { + mmreadSBYTES(buf,4,h->mmf); + } else { + buf[0] = '\0'; // make sure start is \0 + } buf[4] = '\0'; if( strcmp(buf,"MTrk") ) { mid_message("invalid track-chunk '%s' is not 'MTrk'",buf); - MID_Cleanup(h); - avoid_reentry = 0; - return FALSE; + goto ErrorCleanup; } miditracklen = mid_read_long(h); - if (mm.sz < miditracklen) continue; + if (mm.err || mm.sz < miditracklen) continue; runningstatus = 0; if( t && h->midiformat == 1 ) mid_rewind_tracks(h); // tracks sound simultaneously while( miditracklen > 0 ) { + if (mm.err) break; miditracklen -= mid_read_delta(h); midibyte[0] = mid_read_byte(h); miditracklen--; @@ -1378,6 +1416,7 @@ BOOL CSoundFile::ReadMID(const BYTE *lpStream, DWORD dwMemLength) t, (long)(h->tracktime), midibyte[0]); while( midibyte[0] != 0xf7 ) { midibyte[0] = mid_read_byte(h); + if (mm.err) break; miditracklen--; if( h->debug ) printf(" %02X", midibyte[0]); } @@ -1399,6 +1438,7 @@ BOOL CSoundFile::ReadMID(const BYTE *lpStream, DWORD dwMemLength) t, (long)(h->tracktime), metalen); while( metalen > 0 ) { midibyte[1] = mid_read_byte(h); + if (mm.err) break; metalen--; miditracklen--; if( h->debug ) printf(" %02X", midibyte[1]); @@ -1411,13 +1451,14 @@ BOOL CSoundFile::ReadMID(const BYTE *lpStream, DWORD dwMemLength) metalen = h->deltatime; if( metalen > 31 ) metalen = 31; if( metalen ) { - mmreadSBYTES(buf, metalen, h->mmf); + if (!mmreadSBYTES(buf, metalen, h->mmf)) break; miditracklen -= metalen; } buf[metalen] = '\0'; metalen = h->deltatime - metalen; while( metalen > 0 ) { midibyte[1] = mid_read_byte(h); + if (mm.err) break; metalen--; miditracklen--; } @@ -1467,7 +1508,7 @@ BOOL CSoundFile::ReadMID(const BYTE *lpStream, DWORD dwMemLength) } if( miditracklen < 1 && (runningstatus != 0xff || midibyte[0] != 0x2f) ) { delta = mmftell(h->mmf); - mmreadSBYTES(buf,4,h->mmf); + if (!mmreadSBYTES(buf,4,h->mmf)) break; buf[4] = '\0'; if( strcmp(buf,"MTrk") ) { miditracklen = 0x7fffffff; @@ -1545,15 +1586,13 @@ BOOL CSoundFile::ReadMID(const BYTE *lpStream, DWORD dwMemLength) m_dwSongFlags = SONG_LINEARSLIDES; m_nMinPeriod = 28 << 2; m_nMaxPeriod = 1712 << 3; - if (m_nChannels == 0) - return FALSE; + if (m_nChannels == 0) goto ErrorCleanup; + // orderlist for(t=0; t < numpats; t++) Order[t] = t; - if( !PAT_Load_Instruments(this) ) { - avoid_reentry = 0; - return FALSE; - } + if( !PAT_Load_Instruments(this) ) goto ErrorCleanup; + // ============================== // Load the pattern info now! if( MID_ReadPatterns(Patterns, PatternSize, h, numpats, m_nChannels) ) { @@ -1581,4 +1620,10 @@ BOOL CSoundFile::ReadMID(const BYTE *lpStream, DWORD dwMemLength) MID_Cleanup(h); // we dont need it anymore avoid_reentry = 0; // it is safe now, I'm finished return TRUE; + +ErrorCleanup: + MID_Cleanup(h); +ErrorExit: + avoid_reentry = 0; + return FALSE; } diff --git a/src/load_mod.cpp b/src/load_mod.cpp index c8ba8d2b..313ea756 100644 --- a/src/load_mod.cpp +++ b/src/load_mod.cpp @@ -184,7 +184,7 @@ static BOOL IsValidName(LPCSTR s, int length, CHAR minChar) return TRUE; } -BOOL IsMagic(LPCSTR s1, LPCSTR s2) +static BOOL IsMagic(LPCSTR s1, LPCSTR s2) { return ((*(DWORD *)s1) == (*(DWORD *)s2)) ? TRUE : FALSE; } diff --git a/src/load_mt2.cpp b/src/load_mt2.cpp index 692bf515..14ccec3e 100644 --- a/src/load_mt2.cpp +++ b/src/load_mt2.cpp @@ -124,6 +124,19 @@ typedef struct _MT2GROUP #pragma pack() +static int calcNumOnes(int number) { + int cnt = 0; + + while(number) + { + number &= (number -1); + cnt ++; + } + + return(cnt); +} + + static VOID ConvertMT2Command(CSoundFile *that, MODCOMMAND *m, const MT2COMMAND *p) //--------------------------------------------------------------------------- { @@ -190,7 +203,7 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength) const MT2INSTRUMENT *InstrMap[255]; const MT2SAMPLE *SampleMap[256]; - if ((!lpStream) || (dwMemLength < sizeof(MT2FILEHEADER)) + if ((!lpStream) || (dwMemLength < sizeof(MT2FILEHEADER) + 4) || (pfh->dwMT20 != 0x3032544D) || (pfh->wVersion < 0x0200) || (pfh->wVersion >= 0x0300) || (pfh->wChannels < 4) || (pfh->wChannels > 64)) return FALSE; @@ -211,6 +224,7 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength) memcpy(m_szNames[0], pfh->szSongName, 32); m_szNames[0][31] = 0; dwMemPos = sizeof(MT2FILEHEADER); + if (dwMemPos+2 > dwMemLength) return TRUE; nDrumDataLen = *(WORD *)(lpStream + dwMemPos); dwDrumDataPos = dwMemPos + 2; if (nDrumDataLen >= 2) pdd = (MT2DRUMSDATA *)(lpStream+dwDrumDataPos); @@ -236,7 +250,7 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength) DWORD dwId = *(DWORD *)(lpStream+dwMemPos); DWORD dwLen = *(DWORD *)(lpStream+dwMemPos+4); dwMemPos += 8; - if (dwMemPos + dwLen > dwMemLength) return TRUE; + if (dwLen >= dwMemLength || dwMemPos > dwMemLength - dwLen) return TRUE; #ifdef MT2DEBUG CHAR s[5]; memcpy(s, &dwId, 4); @@ -274,7 +288,8 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength) const MT2PATTERN *pmp = (MT2PATTERN *)(lpStream+dwMemPos); UINT wDataLen = (pmp->wDataLen + 1) & ~1; dwMemPos += 6; - if (dwMemPos + wDataLen > dwMemLength) break; + if (dwMemLength - wDataLen > dwMemLength || dwMemPos + wDataLen > dwMemLength) break; + UINT nLines = pmp->wLines; if ((iPat < MAX_PATTERNS) && (nLines > 0) && (nLines <= 256)) { @@ -286,17 +301,20 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength) if (!Patterns[iPat]) return TRUE; MODCOMMAND *m = Patterns[iPat]; UINT len = wDataLen; + if (len <= 4) return TRUE; + if (pfh->fulFlags & 1) // Packed Patterns { - BYTE *p = (BYTE *)(lpStream+dwMemPos); + const BYTE *p = lpStream+dwMemPos; UINT pos = 0, row=0, ch=0; - while (pos < len) + while (pos < len - 4) { MT2COMMAND cmd; UINT infobyte = p[pos++]; UINT rptcount = 0; if (infobyte == 0xff) { + if (pos + 2 > len) break; rptcount = p[pos++]; infobyte = p[pos++]; #if 0 @@ -310,6 +328,7 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength) { UINT patpos = row*m_nChannels+ch; cmd.note = cmd.instr = cmd.vol = cmd.pan = cmd.fxcmd = cmd.fxparam1 = cmd.fxparam2 = 0; + if (pos >= len - calcNumOnes(infobyte & 0x7F)) break; if (infobyte & 1) cmd.note = p[pos++]; if (infobyte & 2) cmd.instr = p[pos++]; if (infobyte & 4) cmd.vol = p[pos++]; @@ -332,11 +351,12 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength) } else { const MT2COMMAND *p = (MT2COMMAND *)(lpStream+dwMemPos); + UINT pos = 0; UINT n = 0; - while ((len > sizeof(MT2COMMAND)) && (n < m_nChannels*nLines)) + while ((pos + sizeof(MT2COMMAND) <= len) && (n < m_nChannels*nLines)) { ConvertMT2Command(this, m, p); - len -= sizeof(MT2COMMAND); + pos += sizeof(MT2COMMAND); n++; p++; m++; @@ -419,10 +439,12 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength) #ifdef MT2DEBUG if (iIns <= pfh->wInstruments) Log(" Instrument #%d at offset %04X: %d bytes\n", iIns, dwMemPos, pmi->dwDataLen); #endif - if (((LONG)pmi->dwDataLen > 0) && (dwMemPos <= dwMemLength - 40) && (pmi->dwDataLen <= dwMemLength - (dwMemPos + 40))) + if (pmi->dwDataLen > dwMemLength - (dwMemPos+36)) return TRUE; + if (pmi->dwDataLen > 0) { + if (dwMemPos + sizeof(MT2INSTRUMENT) - 4 > dwMemLength) return TRUE; InstrMap[iIns-1] = pmi; - if (penv) + if (penv && pmi->dwDataLen >= sizeof(MT2INSTRUMENT) - 40) { penv->nFadeOut = pmi->wFadeOut; penv->nNNA = pmi->wNNA & 3; @@ -433,6 +455,7 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength) if (pfh->wVersion <= 0x201) { DWORD dwEnvPos = dwMemPos + sizeof(MT2INSTRUMENT) - 4; + if (dwEnvPos + 2*sizeof(MT2ENVELOPE) > dwMemLength) return TRUE; pehdr[0] = (MT2ENVELOPE *)(lpStream+dwEnvPos); pehdr[1] = (MT2ENVELOPE *)(lpStream+dwEnvPos+8); pehdr[2] = pehdr[3] = NULL; @@ -442,10 +465,12 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength) } else { DWORD dwEnvPos = dwMemPos + sizeof(MT2INSTRUMENT); + if (dwEnvPos > dwMemLength) return TRUE; for (UINT i=0; i<4; i++) { if (pmi->wEnvFlags1 & (1< dwMemLength) return TRUE; pehdr[i] = (MT2ENVELOPE *)(lpStream+dwEnvPos); pedata[i] = (WORD *)pehdr[i]->EnvData; dwEnvPos += sizeof(MT2ENVELOPE); @@ -455,6 +480,10 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength) pedata[i] = NULL; } } + + // envelopes exceed file length? + if (dwEnvPos > dwMemLength) return TRUE; + } // Load envelopes for (UINT iEnv=0; iEnv<4; iEnv++) if (pehdr[iEnv]) @@ -531,7 +560,7 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength) m_nSamples = (pfh->wSamples < MAX_SAMPLES) ? pfh->wSamples : MAX_SAMPLES-1; for (UINT iSmp=1; iSmp<=256; iSmp++) { - if (dwMemPos+36 > dwMemLength) return TRUE; + if (dwMemPos+36 > dwMemLength || dwMemPos > dwMemLength) return TRUE; const MT2SAMPLE *pms = (MT2SAMPLE *)(lpStream+dwMemPos); #ifdef MT2DEBUG if (iSmp <= m_nSamples) Log(" Sample #%d at offset %04X: %d bytes\n", iSmp, dwMemPos, pms->dwDataLen); @@ -540,6 +569,7 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength) { memcpy(m_szNames[iSmp], pms->szName, 32); } + if (pms->dwDataLen > dwMemLength - (dwMemPos+36)) return TRUE; if (pms->dwDataLen > 0) { SampleMap[iSmp-1] = pms; @@ -573,13 +603,12 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength) #endif for (UINT iMap=0; iMap<255; iMap++) if (InstrMap[iMap]) { - if (dwMemPos+8 > dwMemLength) return TRUE; const MT2INSTRUMENT *pmi = InstrMap[iMap]; INSTRUMENTHEADER *penv = NULL; if (iMapwSamples; iGrp++) { - if (penv) + if (penv && dwMemPos < dwMemLength && dwMemPos < dwMemLength - 8) { const MT2GROUP *pmg = (MT2GROUP *)(lpStream+dwMemPos); for (UINT i=0; i<96; i++) @@ -616,7 +645,7 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength) Log(" Reading sample #%d at offset 0x%04X (len=%d)\n", iData+1, dwMemPos, psmp->nLength); #endif UINT rsflags; - + if (pms->nChannels == 2) rsflags = (psmp->uFlags & CHN_16BIT) ? RS_STPCM16D : RS_STPCM8D; else @@ -625,12 +654,12 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength) dwMemPos += ReadSample(psmp, rsflags, (LPCSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos); } } else - if (dwMemPos+4 < dwMemLength) + if (dwMemPos < dwMemLength-4) { UINT nNameLen = *(DWORD *)(lpStream+dwMemPos); dwMemPos += nNameLen + 16; } - if (dwMemPos+4 >= dwMemLength) break; + if (dwMemPos >= dwMemLength-4) break; } return TRUE; } diff --git a/src/load_okt.cpp b/src/load_okt.cpp index 7968f0b1..764ae320 100644 --- a/src/load_okt.cpp +++ b/src/load_okt.cpp @@ -59,7 +59,7 @@ BOOL CSoundFile::ReadOKT(const BYTE *lpStream, DWORD dwMemLength) // Reading samples for (UINT smp=1; smp <= nsamples; smp++) { - if (dwMemPos >= dwMemLength) return TRUE; + if (dwMemPos >= dwMemLength - sizeof(OKTSAMPLE)) return TRUE; if (smp < MAX_SAMPLES) { OKTSAMPLE *psmp = (OKTSAMPLE *)(lpStream + dwMemPos); @@ -78,39 +78,42 @@ BOOL CSoundFile::ReadOKT(const BYTE *lpStream, DWORD dwMemLength) dwMemPos += sizeof(OKTSAMPLE); } // SPEE - if (dwMemPos >= dwMemLength) return TRUE; + if (dwMemPos >= dwMemLength - 12) return TRUE; if (*((DWORD *)(lpStream + dwMemPos)) == 0x45455053) { m_nDefaultSpeed = lpStream[dwMemPos+9]; dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; } // SLEN - if (dwMemPos >= dwMemLength) return TRUE; + if (dwMemPos + 10 > dwMemLength) return TRUE; if (*((DWORD *)(lpStream + dwMemPos)) == 0x4E454C53) { + if (dwMemPos + 10 > dwMemLength) return TRUE; npatterns = lpStream[dwMemPos+9]; dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; } // PLEN - if (dwMemPos >= dwMemLength) return TRUE; + if (dwMemPos + 10 > dwMemLength) return TRUE; if (*((DWORD *)(lpStream + dwMemPos)) == 0x4E454C50) { + if (dwMemPos + 10 > dwMemLength) return TRUE; norders = lpStream[dwMemPos+9]; dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; } // PATT - if (dwMemPos >= dwMemLength) return TRUE; + if (dwMemPos + 8 > dwMemLength) return TRUE; if (*((DWORD *)(lpStream + dwMemPos)) == 0x54544150) { UINT orderlen = norders; if (orderlen >= MAX_ORDERS) orderlen = MAX_ORDERS-1; - for (UINT i=0; i dwMemLength) return TRUE; + for (UINT i=0; i1; j--) { if (Order[j-1]) break; Order[j-1] = 0xFF; } dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; } // PBOD UINT npat = 0; - while ((dwMemPos+10 < dwMemLength) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4250)) + while ((dwMemPos < dwMemLength - 10) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4250)) { DWORD dwPos = dwMemPos + 10; UINT rows = lpStream[dwMemPos+9]; @@ -186,7 +189,7 @@ BOOL CSoundFile::ReadOKT(const BYTE *lpStream, DWORD dwMemLength) } // SBOD UINT nsmp = 1; - while ((dwMemPos+10 < dwMemLength) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4253)) + while ((dwMemPos < dwMemLength-10) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4253)) { if (nsmp < MAX_SAMPLES) ReadSample(&Ins[nsmp], RS_PCM8S, (LPSTR)(lpStream+dwMemPos+8), dwMemLength-dwMemPos-8); dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; @@ -194,4 +197,3 @@ BOOL CSoundFile::ReadOKT(const BYTE *lpStream, DWORD dwMemLength) } return TRUE; } - diff --git a/src/load_pat.cpp b/src/load_pat.cpp index adcccc3f..6ea86b40 100644 --- a/src/load_pat.cpp +++ b/src/load_pat.cpp @@ -188,7 +188,7 @@ int pat_numinstr(void) int pat_smptogm(int smp) { - if( smp < MAXSMP ) + if( smp && smp < MAXSMP && pat_gm_used[smp - 1] < MAXSMP ) return pat_gm_used[smp - 1]; return 1; } diff --git a/src/load_psm.cpp b/src/load_psm.cpp index 4e72afad..7d741d52 100644 --- a/src/load_psm.cpp +++ b/src/load_psm.cpp @@ -98,16 +98,17 @@ void swap_PSMSAMPLE(PSMSAMPLE* p){ BOOL CSoundFile::ReadPSM(LPCBYTE lpStream, DWORD dwMemLength) //----------------------------------------------------------- { - PSMCHUNK pfh = *(const PSMCHUNK *)lpStream; + PSMCHUNK pfh; DWORD dwMemPos, dwSongPos; DWORD smpnames[MAX_SAMPLES]; DWORD patptrs[MAX_PATTERNS]; BYTE samplemap[MAX_SAMPLES]; - UINT nPatterns; + UINT nPatterns = 0; if (dwMemLength < 256) return FALSE; // Swap chunk + pfh = *(const PSMCHUNK *)lpStream; swap_PSMCHUNK(&pfh); // Chunk0: "PSM ",filesize,"FILE" @@ -279,14 +280,17 @@ BOOL CSoundFile::ReadPSM(LPCBYTE lpStream, DWORD dwMemLength) { PSMPATTERN pPsmPat = *(const PSMPATTERN *)(lpStream+patptrs[nPat]+8); swap_PSMPATTERN(&pPsmPat); - ULONG len = *(DWORD *)(lpStream+patptrs[nPat]+4) - 12; + PSMCHUNK pchunk = *(const PSMCHUNK *)(lpStream+patptrs[nPat]); + swap_PSMCHUNK(&pchunk); + + ULONG len = pchunk.len - 12; UINT nRows = pPsmPat.rows; if (len > pPsmPat.size) len = pPsmPat.size; if ((nRows < 64) || (nRows > 256)) nRows = 64; PatternSize[nPat] = nRows; if ((Patterns[nPat] = AllocatePattern(nRows, m_nChannels)) == NULL) break; MODCOMMAND *m = Patterns[nPat]; - BYTE *p = pPsmPat.data; + const BYTE *p = lpStream + patptrs[nPat] + 20; MODCOMMAND *sp, dummy; UINT pos = 0; UINT row = 0; @@ -313,25 +317,28 @@ BOOL CSoundFile::ReadPSM(LPCBYTE lpStream, DWORD dwMemLength) ch = p[pos++]; if (ch >= m_nChannels) { sp = &dummy; - } else { + } else { sp = &m[ch]; - } + } // Note + Instr - if ((flags & 0x80) && (pos+1 < len)) - { - UINT note = p[pos++]; - note = (note>>4)*12+(note&0x0f)+12+1; - if (note > 0x80) note = 0; + if ((flags & 0x80) && (pos+1 < len)) + { + UINT note = p[pos++]; + note = (note>>4)*12+(note&0x0f)+12+1; + if (note > 0x80) note = 0; sp->note = note; - } + } if ((flags & 0x40) && (pos+1 < len)) { UINT nins = p[pos++]; + if (nins >= m_nSamples) { #ifdef PSM_LOG //if (!nPat) Log("note+ins: %02X.%02X\n", note, nins); if ((!nPat) && (nins >= m_nSamples)) Log("WARNING: invalid instrument number (%d)\n", nins); #endif - sp->instr = samplemap[nins]; + } else { + sp->instr = samplemap[nins]; + } } // Volume if ((flags & 0x20) && (pos < len)) diff --git a/src/load_s3m.cpp b/src/load_s3m.cpp index ef61f601..ce42f879 100644 --- a/src/load_s3m.cpp +++ b/src/load_s3m.cpp @@ -252,8 +252,10 @@ BOOL CSoundFile::ReadS3M(const BYTE *lpStream, DWORD dwMemLength) UINT iord = psfh.ordnum; if (iord<1) iord = 1; if (iord > MAX_ORDERS) iord = MAX_ORDERS; + if (dwMemPos + iord + 1 >= dwMemLength) return FALSE; if (iord) { + if (dwMemPos + iord > dwMemLength) return FALSE; memcpy(Order, lpStream+dwMemPos, iord); dwMemPos += iord; } @@ -271,6 +273,7 @@ BOOL CSoundFile::ReadS3M(const BYTE *lpStream, DWORD dwMemLength) if (nins+npat) { + if (dwMemPos + 2*(nins+npat) >= dwMemLength) return FALSE; memcpy(ptr, lpStream+dwMemPos, 2*(nins+npat)); dwMemPos += 2*(nins+npat); for (UINT j = 0; j < (nins+npat); ++j) { @@ -278,7 +281,10 @@ BOOL CSoundFile::ReadS3M(const BYTE *lpStream, DWORD dwMemLength) } if (psfh.panning_present == 252) { + if (dwMemPos + 32 > dwMemLength) return FALSE; + const BYTE *chnpan = lpStream+dwMemPos; + if (dwMemPos > dwMemLength - 32) return FALSE; for (UINT i=0; i<32; i++) if (chnpan[i] & 0x20) { ChnSettings[i].nPan = ((chnpan[i] & 0x0F) << 4) + 8; diff --git a/src/load_stm.cpp b/src/load_stm.cpp index 6f55b78e..6f0da3ee 100644 --- a/src/load_stm.cpp +++ b/src/load_stm.cpp @@ -61,7 +61,7 @@ BOOL CSoundFile::ReadSTM(const BYTE *lpStream, DWORD dwMemLength) { const STMHEADER *phdr = (STMHEADER *)lpStream; DWORD dwMemPos = 0; - + if ((!lpStream) || (dwMemLength < sizeof(STMHEADER))) return FALSE; if ((phdr->filetype != 2) || (phdr->unused != 0x1A) || ((strncasecmp(phdr->trackername, "!SCREAM!", 8)) @@ -107,6 +107,7 @@ BOOL CSoundFile::ReadSTM(const BYTE *lpStream, DWORD dwMemLength) dwMemPos = sizeof(STMHEADER); for (UINT nOrd=0; nOrd= 99) Order[nOrd] = 0xFF; UINT nPatterns = phdr->numpat; + if (nPatterns > MAX_PATTERNS) nPatterns = MAX_PATTERNS; for (UINT nPat=0; nPat dwMemLength) return TRUE; @@ -183,4 +184,3 @@ BOOL CSoundFile::ReadSTM(const BYTE *lpStream, DWORD dwMemLength) } return TRUE; } - diff --git a/src/load_ult.cpp b/src/load_ult.cpp index 83024f21..eddc9a43 100644 --- a/src/load_ult.cpp +++ b/src/load_ult.cpp @@ -146,7 +146,7 @@ BOOL CSoundFile::ReadUlt(const BYTE *lpStream, DWORD dwMemLength) for (UINT nPat=0; nPat dwMemLength) return TRUE; + if (dwMemPos + 5 > dwMemLength) return TRUE; UINT rep = 1; UINT note = lpStream[dwMemPos++]; if (note == 0xFC) { + if (dwMemPos + 7 > dwMemLength) return TRUE; rep = lpStream[dwMemPos]; note = lpStream[dwMemPos+1]; dwMemPos += 2; + if (dwMemPos + 4 > dwMemLength) return TRUE; } + UINT instr = lpStream[dwMemPos++]; UINT eff = lpStream[dwMemPos++]; UINT dat1 = lpStream[dwMemPos++]; @@ -221,4 +224,3 @@ BOOL CSoundFile::ReadUlt(const BYTE *lpStream, DWORD dwMemLength) } return TRUE; } - diff --git a/src/load_wav.cpp b/src/load_wav.cpp index cf721df3..48de6137 100644 --- a/src/load_wav.cpp +++ b/src/load_wav.cpp @@ -18,9 +18,9 @@ BOOL CSoundFile::ReadWav(const BYTE *lpStream, DWORD dwMemLength) //--------------------------------------------------------------- { DWORD dwMemPos = 0; - WAVEFILEHEADER *phdr = (WAVEFILEHEADER *)lpStream; - WAVEFORMATHEADER *pfmt = (WAVEFORMATHEADER *)(lpStream + sizeof(WAVEFILEHEADER)); - if ((!lpStream) || (dwMemLength < (DWORD)sizeof(WAVEFILEHEADER))) return FALSE; + const WAVEFILEHEADER *phdr = (WAVEFILEHEADER *)lpStream; + const WAVEFORMATHEADER *pfmt = (WAVEFORMATHEADER *)(lpStream + sizeof(WAVEFILEHEADER)); + if ((!lpStream) || (dwMemLength < sizeof(WAVEFILEHEADER)+sizeof(WAVEFORMATHEADER))) return FALSE; if ((phdr->id_RIFF != IFFID_RIFF) || (phdr->id_WAVE != IFFID_WAVE) || (pfmt->id_fmt != IFFID_fmt)) return FALSE; dwMemPos = sizeof(WAVEFILEHEADER) + 8 + pfmt->hdrlen; @@ -32,11 +32,12 @@ BOOL CSoundFile::ReadWav(const BYTE *lpStream, DWORD dwMemLength) || (pfmt->bitspersample & 7) || (pfmt->bitspersample < 8) || (pfmt->bitspersample > 32)) return FALSE; - WAVEDATAHEADER *pdata; + const WAVEDATAHEADER *pdata; for (;;) { pdata = (WAVEDATAHEADER *)(lpStream + dwMemPos); if (pdata->id_data == IFFID_data) break; + if (pdata->length >= dwMemLength || dwMemPos > dwMemLength - pdata->length) return FALSE; dwMemPos += pdata->length + 8; if (dwMemPos >= dwMemLength - 8) return FALSE; } diff --git a/src/load_xm.cpp b/src/load_xm.cpp index 3a22b7da..cc1f89cc 100644 --- a/src/load_xm.cpp +++ b/src/load_xm.cpp @@ -166,7 +166,7 @@ BOOL CSoundFile::ReadXM(const BYTE *lpStream, DWORD dwMemLength) dwMemPos++; dwSize = bswapLE32(*((DWORD *)(lpStream+dwMemPos))); } - if (dwMemPos + 9 > dwMemLength) return TRUE; + if (dwMemPos + 9 > dwMemLength) return TRUE; rows = bswapLE16(*((WORD *)(lpStream+dwMemPos+5))); if ((!rows) || (rows > 256)) rows = 64; packsize = bswapLE16(*((WORD *)(lpStream+dwMemPos+7))); @@ -193,13 +193,14 @@ BOOL CSoundFile::ReadXM(const BYTE *lpStream, DWORD dwMemLength) UINT vol = 0; if (b & 0x80) { - if (b & 1) p->note = src[j++]; - if (b & 2) p->instr = src[j++]; - if (b & 4) vol = src[j++]; - if (b & 8) p->command = src[j++]; - if (b & 16) p->param = src[j++]; + if (b & 1) p->note = j < packsize ? src[j++] : 0; + if (b & 2) p->instr = j < packsize ? src[j++] : 0; + if (b & 4) vol = j < packsize ? src[j++] : 0; + if (b & 8) p->command = j < packsize ? src[j++] : 0; + if (b & 16) p->param = j < packsize ? src[j++] : 0; } else { + if (j + 5 > packsize) break; p->note = b; p->instr = src[j++]; vol = src[j++]; @@ -281,16 +282,18 @@ BOOL CSoundFile::ReadXM(const BYTE *lpStream, DWORD dwMemLength) DWORD samplesize[32]; UINT samplemap[32]; WORD nsamples; + DWORD pihlen; if (dwMemPos + sizeof(XMINSTRUMENTHEADER) >= dwMemLength) return TRUE; pih = (XMINSTRUMENTHEADER *)(lpStream+dwMemPos); - if (dwMemPos + bswapLE32(pih->size) > dwMemLength) return TRUE; + pihlen = bswapLE32(pih->size); + if (pihlen >= dwMemLength || dwMemPos > dwMemLength - pihlen) return TRUE; if ((Headers[iIns] = new INSTRUMENTHEADER) == NULL) continue; memset(Headers[iIns], 0, sizeof(INSTRUMENTHEADER)); memcpy(Headers[iIns]->name, pih->name, 22); if ((nsamples = pih->samples) > 0) { - if (dwMemPos + sizeof(XMSAMPLEHEADER) > dwMemLength) return TRUE; + if (dwMemPos + sizeof(XMINSTRUMENTHEADER) + sizeof(XMSAMPLEHEADER) > dwMemLength) return TRUE; memcpy(&xmsh, lpStream+dwMemPos+sizeof(XMINSTRUMENTHEADER), sizeof(XMSAMPLEHEADER)); xmsh.shsize = bswapLE32(xmsh.shsize); for (int i = 0; i < 24; ++i) { @@ -299,10 +302,10 @@ BOOL CSoundFile::ReadXM(const BYTE *lpStream, DWORD dwMemLength) } xmsh.volfade = bswapLE16(xmsh.volfade); xmsh.res = bswapLE16(xmsh.res); - dwMemPos += bswapLE32(pih->size); + dwMemPos += pihlen; } else { - if (bswapLE32(pih->size)) dwMemPos += bswapLE32(pih->size); + if (pihlen) dwMemPos += pihlen; else dwMemPos += sizeof(XMINSTRUMENTHEADER); continue; } @@ -439,7 +442,7 @@ BOOL CSoundFile::ReadXM(const BYTE *lpStream, DWORD dwMemLength) for (UINT ins=0; ins dwMemLength) - || (dwMemPos + xmsh.shsize > dwMemLength)) return TRUE; + || (xmsh.shsize >= dwMemLength) || (dwMemPos > dwMemLength - xmsh.shsize)) return TRUE; memcpy(&xmss, lpStream+dwMemPos, sizeof(xmss)); xmss.samplen = bswapLE32(xmss.samplen); xmss.loopstart = bswapLE32(xmss.loopstart); @@ -536,6 +539,7 @@ BOOL CSoundFile::ReadXM(const BYTE *lpStream, DWORD dwMemLength) { UINT len = *((DWORD *)(lpStream+dwMemPos+4)); dwMemPos += 8; + if (len >= dwMemLength || dwMemPos > dwMemLength - len) return TRUE; if (len == sizeof(MODMIDICFG)) { memcpy(&m_MidiCfg, lpStream+dwMemPos, len); @@ -547,7 +551,8 @@ BOOL CSoundFile::ReadXM(const BYTE *lpStream, DWORD dwMemLength) { UINT len = *((DWORD *)(lpStream+dwMemPos+4)); dwMemPos += 8; - if ((dwMemPos + len <= dwMemLength) && (len <= MAX_PATTERNS*MAX_PATTERNNAME) && (len >= MAX_PATTERNNAME)) + if (len >= dwMemLength || dwMemPos > dwMemLength - len) return TRUE; + if ((len <= MAX_PATTERNS*MAX_PATTERNNAME) && (len >= MAX_PATTERNNAME)) { m_lpszPatternNames = new char[len]; @@ -564,7 +569,8 @@ BOOL CSoundFile::ReadXM(const BYTE *lpStream, DWORD dwMemLength) { UINT len = *((DWORD *)(lpStream+dwMemPos+4)); dwMemPos += 8; - if ((dwMemPos + len <= dwMemLength) && (len <= MAX_BASECHANNELS*MAX_CHANNELNAME)) + if (len >= dwMemLength || dwMemPos > dwMemLength - len) return TRUE; + if (len <= MAX_BASECHANNELS*MAX_CHANNELNAME) { UINT n = len / MAX_CHANNELNAME; for (UINT i=0; i= dwMemLength - 20) break; - memcpy(tmp1, lpMemFile+dwMemPos, 28); pblk = (LPMMCMPBLOCK)(tmp1); psubblk = (LPMMCMPSUBBLOCK)(tmp1+20); + + memcpy(pblk, lpMemFile+dwMemPos, 20); swap_block(pblk); - swap_subblock(psubblk); - if (dwMemPos + 20 + pblk->sub_blk*8 >= dwMemLength) break; + if (pblk->sub_blk*8 >= dwMemLength - dwMemPos - 20) break; dwSubPos = dwMemPos + 20; dwMemPos += 20 + pblk->sub_blk*8; + + if (!pblk->sub_blk) continue; + memcpy(psubblk, lpMemFile + dwSubPos, 8); + swap_subblock(psubblk); + #ifdef MMCMP_LOG Log("block %d: flags=%04X sub_blocks=%d", nBlock, (UINT)pblk->flags, (UINT)pblk->sub_blk); Log(" pksize=%d unpksize=%d", pblk->pk_size, pblk->unpk_size); @@ -213,7 +218,7 @@ BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength) #endif memcpy(pBuffer+psubblk->unpk_pos, lpMemFile+dwMemPos, psubblk->unpk_size); dwMemPos += psubblk->unpk_size; - memcpy(tmp1+20,lpMemFile+dwSubPos+i*8,8); + memcpy(psubblk,lpMemFile+dwSubPos+i*8,8); swap_subblock(psubblk); } } else @@ -227,8 +232,8 @@ BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength) UINT numbits = pblk->num_bits; UINT subblk = 0, oldval = 0; - if (dwSize * 2 > dwFileSize-psubblk->unpk_pos || - psubblk->unpk_pos > dwMemLength-dwMemPos) + if (psubblk->unpk_pos >= dwFileSize || + dwSize * 2 > dwFileSize - psubblk->unpk_pos) break; #ifdef MMCMP_LOG @@ -248,11 +253,6 @@ BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength) UINT newval = 0x10000; DWORD d = bb.GetBits(numbits+1); - if ((psubblk->unpk_pos >= dwFileSize) || - (psubblk->unpk_size >= dwFileSize) || - (psubblk->unpk_size > dwFileSize - psubblk->unpk_pos)) - dwPos = dwSize; - if (d >= MMCMP16BitCommands[numbits]) { UINT nFetch = MMCMP16BitFetch[numbits]; @@ -293,12 +293,12 @@ BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength) if (dwPos >= dwSize) { subblk++; - memcpy(tmp1+20,lpMemFile+dwSubPos+subblk*8,8); + memcpy(psubblk,lpMemFile+dwSubPos+subblk*8,8); swap_subblock(psubblk); dwPos = 0; dwSize = psubblk->unpk_size >> 1; if ( psubblk->unpk_pos >= dwFileSize || - dwSize * 2 > dwFileSize ) { + dwSize * 2 > dwFileSize - psubblk->unpk_pos) { break; } pDest = (LPWORD)(pBuffer + psubblk->unpk_pos); @@ -315,8 +315,8 @@ BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength) UINT subblk = 0, oldval = 0; LPCBYTE ptable = lpMemFile+dwMemPos; - if (dwSize > dwFileSize-psubblk->unpk_pos || - psubblk->unpk_pos > dwMemLength-dwMemPos) + if (psubblk->unpk_pos >= dwFileSize || + dwSize > dwFileSize - psubblk->unpk_pos) break; bb.bitcount = 0; @@ -324,17 +324,12 @@ BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength) bb.pSrc = lpMemFile+dwMemPos+pblk->tt_entries; bb.pEnd = lpMemFile+dwMemPos+pblk->pk_size; if (bb.pEnd > lpMemFile+dwMemLength) - bb.pEnd = lpMemFile+dwMemLength; + bb.pEnd = lpMemFile+dwMemLength; while (subblk < pblk->sub_blk) { UINT newval = 0x100; DWORD d = bb.GetBits(numbits+1); - if ((psubblk->unpk_pos >= dwFileSize) || - (psubblk->unpk_size >= dwFileSize) || - (psubblk->unpk_size > dwFileSize - (psubblk->unpk_pos))) - dwPos = dwSize; - if (d >= MMCMP8BitCommands[numbits]) { UINT nFetch = MMCMP8BitFetch[numbits]; @@ -370,12 +365,12 @@ BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength) if (dwPos >= dwSize) { subblk++; - memcpy(tmp1+20,lpMemFile+dwSubPos+subblk*8,8); + memcpy(psubblk,lpMemFile+dwSubPos+subblk*8, 8); swap_subblock(psubblk); dwPos = 0; dwSize = psubblk->unpk_size; if ( psubblk->unpk_pos >= dwFileSize || - dwSize > dwFileSize ) + dwSize > dwFileSize - psubblk->unpk_pos) break; pDest = pBuffer + psubblk->unpk_pos; } diff --git a/src/sndfile.cpp b/src/sndfile.cpp index 2dfc79e2..5b870a38 100644 --- a/src/sndfile.cpp +++ b/src/sndfile.cpp @@ -1365,11 +1365,12 @@ UINT CSoundFile::ReadSample(MODINSTRUMENT *pIns, UINT nFlags, LPCSTR lpMemFile, { const char *psrc = lpMemFile; char packcharacter = lpMemFile[8], *pdest = (char *)pIns->pSample; - len += bswapLE32(*((LPDWORD)(lpMemFile+4))); - if (len > dwMemLength) len = dwMemLength; + UINT smplen = bswapLE32(*((LPDWORD)(lpMemFile+4))); + if (smplen > dwMemLength - 9) smplen = dwMemLength - 9; + len += smplen; UINT dmax = pIns->nLength; if (pIns->uFlags & CHN_16BIT) dmax <<= 1; - AMSUnpack(psrc+9, len-9, pdest, dmax, packcharacter); + AMSUnpack(psrc+9, smplen, pdest, dmax, packcharacter); } break;