diff -urN 12-STYMulator-0.21a_load_errors/src/stsoundlib/digidrum.cpp 13-STYMulator-0.21a-fail_on_bogus_data/src/stsoundlib/digidrum.cpp --- 12-STYMulator-0.21a_load_errors/src/stsoundlib/digidrum.cpp 2010-04-21 23:39:57.776202559 +0200 +++ 13-STYMulator-0.21a-fail_on_bogus_data/src/stsoundlib/digidrum.cpp 2010-04-22 10:03:36.403718119 +0200 @@ -30,6 +30,7 @@ -----------------------------------------------------------------------------*/ #include "YmTypes.h" +#include "digidrum.h" static ymu8 sample00[631]={ 0xCC,0x84,0xB4,0x70,0x90,0x94,0x70,0x80,0x80,0xAC, @@ -2565,7 +2566,7 @@ 0x80,0x80,0x80,0x80,0x80,0x80,}; /***********************************************************/ -ymu8 *sampleAdress[40] = { +ymu8 *sampleAdress[MAX_DIGIDRUM] = { sample00,sample01,sample02,sample03,sample04,sample05,sample06,sample07, sample08,sample09,sample10,sample11,sample12,sample13,sample14,sample15, sample16,sample17,sample18,sample19,sample20,sample21,sample22,sample23, @@ -2574,7 +2575,7 @@ /***********************************************************/ -ymu32 sampleLen[40] = { +ymu32 sampleLen[MAX_DIGIDRUM] = { 631, 631, 490, 490, 699, 505, 727, 480, 2108, 4231, 378, 1527, 258, 258, 451, 1795, 271, 633, 1379, 147, 139, 85, 150, 507, diff -urN 12-STYMulator-0.21a_load_errors/src/stsoundlib/digidrum.h 13-STYMulator-0.21a-fail_on_bogus_data/src/stsoundlib/digidrum.h --- 12-STYMulator-0.21a_load_errors/src/stsoundlib/digidrum.h 2010-04-21 23:39:57.776202559 +0200 +++ 13-STYMulator-0.21a-fail_on_bogus_data/src/stsoundlib/digidrum.h 2010-04-22 09:59:40.920432933 +0200 @@ -32,6 +32,8 @@ #ifndef __DIGIDRUM__ #define __DIGIDRUM__ +#define MAX_DIGIDRUM 40 + extern ymu8 * sampleAdress[]; extern ymu32 sampleLen[]; diff -urN 12-STYMulator-0.21a_load_errors/src/stsoundlib/Ymload.cpp 13-STYMulator-0.21a-fail_on_bogus_data/src/stsoundlib/Ymload.cpp --- 12-STYMulator-0.21a_load_errors/src/stsoundlib/Ymload.cpp 2010-04-21 23:41:33.307194724 +0200 +++ 13-STYMulator-0.21a-fail_on_bogus_data/src/stsoundlib/Ymload.cpp 2010-04-25 12:19:13.358112601 +0200 @@ -51,6 +51,12 @@ } } +void myFree(void **pPtr) +{ + if (*pPtr) free(*pPtr); + *pPtr = NULL; +} + char *mstrdup(const char *in) { char *out = (char*)malloc(strlen(in)+1); @@ -58,54 +64,84 @@ return out; } -ymu32 readMotorolaDword(ymu8 **ptr) +ymu32 readMotorolaDword(ymu8 **ptr, ymint *ptr_size) { -ymu32 n; +ymu32 n = 0; ymu8 *p = *ptr; - - n = (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3]; - p+=4; - *ptr = p; + if (*ptr_size>=4) + { + n = (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3]; + p+=4; + *ptr = p; + } + (*ptr_size)+=4; return n; } -ymu16 readMotorolaWord(ymu8 **ptr) +ymu16 readMotorolaWord(ymu8 **ptr, ymint *ptr_size) { -ymu16 n; +ymu16 n = 0; ymu8 *p = *ptr; - - n = (p[0]<<8)|p[1]; - p+=2; - *ptr = p; + if (*ptr_size>=2) + { + n = (p[0]<<8)|p[1]; + p+=2; + *ptr = p; + } + (*ptr_size)+=2; return n; } -ymchar *readNtString(ymchar **ptr) +ymchar *readNtString(ymchar **ptr, ymint *ptr_size) { ymchar *p; +ymint len = 0; - p = mstrdup(*ptr); - (*ptr) += strlen(*ptr)+1; + if (*ptr_size<=0) + { + (*ptr_size)-=1; + return mstrdup(""); + } + p=*ptr; + while(*p) + { + p++; + (*ptr_size)--; + len++; + if (*ptr_size==0) + { + (*ptr_size)-=1; + return mstrdup(""); + } + } + p = mstrdup(*ptr); + (*ptr) += len+1; return p; } -yms32 ReadLittleEndian32(ymu8 *pLittle) +yms32 ReadLittleEndian32(ymu8 *pLittle, ymint ptr_size) { - yms32 v = ( (pLittle[0]<<0) | + yms32 v = 0; + if (ptr_size>=4) + { + v = ( (pLittle[0]<<0) | (pLittle[1]<<8) | (pLittle[2]<<16) | (pLittle[3]<<24)); - + } return v; } -yms32 ReadBigEndian32(ymu8 *pBig) +yms32 ReadBigEndian32(ymu8 *pBig, ymint ptr_size) { - yms32 v = ( (pBig[0]<<24) | + yms32 v = 0; + if (ptr_size>=4) + { + v = ( (pBig[0]<<24) | (pBig[1]<<16) | (pBig[2]<<8) | - (pBig[3]<<0)); - + (pBig[3]<<0)); + } return v; } @@ -114,6 +150,13 @@ lzhHeader_t *pHeader; ymu8 *pNew; ymu8 *pSrc; + ymint ptr_left = fileSize; + ymint dummy; + + if (ptr_left < (ymint)sizeof(lzhHeader_t)) + { + return pBigMalloc; + } pHeader = (lzhHeader_t*)pBigMalloc; @@ -123,8 +166,6 @@ return pBigMalloc; } - fileSize = (ymu32)-1; - if (pHeader->level != 0) // NOTE: Endianness works because value is 0 { // Compression LH5, header !=0 : Error. free(pBigMalloc); @@ -133,7 +174,8 @@ return NULL; } - fileSize = ReadLittleEndian32((ymu8*)&pHeader->original); + dummy = 4; + fileSize = ReadLittleEndian32((ymu8*)&pHeader->original, dummy); pNew = (ymu8*)malloc(fileSize); if (!pNew) { @@ -144,10 +186,20 @@ } pSrc = pBigMalloc+sizeof(lzhHeader_t)+pHeader->name_lenght; // NOTE: Endianness works because name_lenght is a byte + ptr_left -= sizeof(lzhHeader_t)+pHeader->name_lenght; pSrc += 2; // skip CRC16 + ptr_left -= 2; - const int packedSize = ReadLittleEndian32((ymu8*)&pHeader->packed); + dummy = 4; + const int packedSize = ReadLittleEndian32((ymu8*)&pHeader->packed, dummy); + + if (packedSize > ptr_left) + { + setLastError("File too small"); + free(pNew); + return pBigMalloc; + } // alloc space for depacker and depack data CLzhDepacker *pDepacker = new CLzhDepacker; @@ -229,19 +281,29 @@ { ymu8 *pUD; ymu8 *ptr; + ymint ptr_size = fileSize; ymint skip; ymint i; ymu32 sampleSize; yms32 tmp; ymu32 id; - - id = ReadBigEndian32((unsigned char*)pBigMalloc); + if (ptr_size < 4) + { + setLastError("File too small"); + return YMFALSE; + } + id = ReadBigEndian32((unsigned char*)pBigMalloc, ptr_size); switch (id) { case 0x594d3221 /*'YM2!'*/: // MADMAX specific. songType = YM_V2; nbFrame = (fileSize-4)/14; + if (nbFrame == 0) + { + setLastError("No frames in file"); + return YMFALSE; + } loopFrame = 0; ymChip.setClock(ATARI_CLOCK); setPlayerRate(50); @@ -259,6 +321,11 @@ case 0x594d3321 /*'YM3!'*/: // Standart YM-Atari format. songType = YM_V3; nbFrame = (fileSize-4)/14; + if (nbFrame == 0) + { + setLastError("No frames in file"); + return YMFALSE; + } loopFrame = 0; ymChip.setClock(ATARI_CLOCK); setPlayerRate(50); @@ -274,10 +341,23 @@ break; case 0x594d3362 /*'YM3b'*/: // Standart YM-Atari format + Loop info. + if (ptr_size < 4) + { + setLastError("File too small"); + return YMFALSE; + } pUD = (ymu8*)(pBigMalloc+fileSize-4); songType = YM_V3; nbFrame = (fileSize-8)/14; - loopFrame = ReadLittleEndian32(pUD); + if (nbFrame == 0) + { + setLastError("No frames in file"); + return YMFALSE; + } + { + ymint dummy = 4; + loopFrame = ReadLittleEndian32(pUD, dummy); + } ymChip.setClock(ATARI_CLOCK); setPlayerRate(50); pDataStream = pBigMalloc+4; @@ -298,28 +378,55 @@ case 0x594d3521 /*'YM5!'*/: // Extended YM2149 format, all machines. case 0x594d3621 /*'YM6!'*/: // Extended YM2149 format, all machines. + if (ptr_size < 12) + { + setLastError("File too small"); + return YMFALSE; + } if (strncmp((const char*)(pBigMalloc+4),"LeOnArD!",8)) { setLastError("Not a valid YM format !"); return YMFALSE; } ptr = pBigMalloc+12; - nbFrame = readMotorolaDword(&ptr); - setAttrib(readMotorolaDword(&ptr)); - nbDrum = readMotorolaWord(&ptr); - ymChip.setClock(readMotorolaDword(&ptr)); - setPlayerRate(readMotorolaWord(&ptr)); - loopFrame = readMotorolaDword(&ptr); - skip = readMotorolaWord(&ptr); + ptr_size -= 12; + nbFrame = readMotorolaDword(&ptr, &ptr_size); + setAttrib(readMotorolaDword(&ptr, &ptr_size)); + nbDrum = readMotorolaWord(&ptr, &ptr_size); + ymChip.setClock(readMotorolaDword(&ptr, &ptr_size)); + setPlayerRate(readMotorolaWord(&ptr, &ptr_size)); + loopFrame = readMotorolaDword(&ptr, &ptr_size); + skip = readMotorolaWord(&ptr, &ptr_size); ptr += skip; + ptr_size -= skip; + if (ptr_size <= 0) + { + setLastError("File too small"); + return YMFALSE; + } if (nbDrum>0) { - pDrumTab=(digiDrum_t*)malloc(nbDrum*sizeof(digiDrum_t)); + pDrumTab=(digiDrum_t*)calloc(nbDrum, sizeof(digiDrum_t)); for (i=0;i= 0x80000000) + { + setLastError("To big drumtab"); + goto error_out; + } + if (ptr_size<(ymint)pDrumTab[i].size) + { + setLastError("File too small"); + goto error_out; + } pDrumTab[i].pData = (ymu8*)malloc(pDrumTab[i].size); memcpy(pDrumTab[i].pData,ptr,pDrumTab[i].size); if (attrib&A_DRUM4BITS) @@ -333,17 +440,19 @@ } } ptr += pDrumTab[i].size; - } - else - { - pDrumTab[i].pData = NULL; + ptr_size -= pDrumTab[i].size; } } attrib &= (~A_DRUM4BITS); } - pSongName = readNtString((char**)&ptr); - pSongAuthor = readNtString((char**)&ptr); - pSongComment = readNtString((char**)&ptr); + pSongName = readNtString((char**)&ptr, &ptr_size); + pSongAuthor = readNtString((char**)&ptr, &ptr_size); + pSongComment = readNtString((char**)&ptr, &ptr_size); + if (ptr_size <= 0) + { + setLastError("File too small"); + goto error_out; + } songType = YM_V5; if (id==0x594d3621/*'YM6!'*/) { @@ -354,6 +463,16 @@ { pSongType = mstrdup("YM 5"); } + if ((nbFrame >= 0x08000000) || (nbFrame < 0)) + { + setLastError("Too many frames"); + goto error_out; + } + if (ptr_size < (ymint)(nbFrame * 16)) + { + setLastError("File too small"); + goto error_out; + } pDataStream = ptr; streamInc = 16; setAttrib(A_STREAMINTERLEAVED|A_TIMECONTROL); @@ -361,6 +480,11 @@ break; case 0x4d495831 /*'MIX1'*/: // ATARI Remix digit format. + if (ptr_size < 12) + { + setLastError("File too small"); + return YMFALSE; + } if (strncmp((const char*)(pBigMalloc+4),"LeOnArD!",8)) { @@ -368,23 +492,50 @@ return YMFALSE; } ptr = pBigMalloc+12; + ptr_size -= 12; songType = YM_MIX1; - tmp = readMotorolaDword(&ptr); + tmp = readMotorolaDword(&ptr, &ptr_size); setAttrib(0); if (tmp&1) setAttrib(A_DRUMSIGNED); - sampleSize = readMotorolaDword(&ptr); - nbMixBlock = readMotorolaDword(&ptr); + sampleSize = readMotorolaDword(&ptr, &ptr_size); + nbMixBlock = readMotorolaDword(&ptr, &ptr_size); + if (ptr_size <= 0) + { + setLastError("File too small"); + goto error_out; + } + if (sampleSize <= 0) + { + setLastError("Invalid sampleSize"); + goto error_out; + } + if (nbMixBlock <= 0) + { + setLastError("Invalid number of mixblocks"); + goto error_out; + } pMixBlock = (mixBlock_t*)malloc(nbMixBlock*sizeof(mixBlock_t)); for (i=0;i=0x80000000) + { + setLastError("Invalid sampleSize"); + goto error_out; + } + if (ptr_size < (ymint)sampleSize) + { + setLastError("File too small"); + goto error_out; + } pBigSampleBuffer = (unsigned char*)malloc(sampleSize); memcpy(pBigSampleBuffer,ptr,sampleSize); @@ -419,33 +570,55 @@ ; NT Music comment ; nb digi * */ + if (ptr_size < 12) + { + setLastError("File too small"); + return YMFALSE; + } + if (strncmp((const char*)(pBigMalloc+4),"LeOnArD!",8)) { setLastError("Not a valid YM format !"); return YMFALSE; } ptr = pBigMalloc+12; + ptr_size -= 12; songType = YM_TRACKER1; - nbVoice = readMotorolaWord(&ptr); - setPlayerRate(readMotorolaWord(&ptr)); - nbFrame= readMotorolaDword(&ptr); - loopFrame = readMotorolaDword(&ptr); - nbDrum = readMotorolaWord(&ptr); - attrib = readMotorolaDword(&ptr); - pSongName = readNtString((char**)&ptr); - pSongAuthor = readNtString((char**)&ptr); - pSongComment = readNtString((char**)&ptr); + nbVoice = readMotorolaWord(&ptr, &ptr_size); + setPlayerRate(readMotorolaWord(&ptr, &ptr_size)); + nbFrame= readMotorolaDword(&ptr, &ptr_size); + loopFrame = readMotorolaDword(&ptr, &ptr_size); + nbDrum = readMotorolaWord(&ptr, &ptr_size); + attrib = readMotorolaDword(&ptr, &ptr_size); + pSongName = readNtString((char**)&ptr, &ptr_size); + pSongAuthor = readNtString((char**)&ptr, &ptr_size); + pSongComment = readNtString((char**)&ptr, &ptr_size); + if (ptr_size < 0) + { + setLastError("File too small"); + return YMFALSE; + } if (nbDrum>0) { - pDrumTab=(digiDrum_t*)malloc(nbDrum*sizeof(digiDrum_t)); + pDrumTab=(digiDrum_t*)calloc(nbDrum, sizeof(digiDrum_t)); for (i=0;i<(ymint)nbDrum;i++) { - pDrumTab[i].size = readMotorolaWord(&ptr); + pDrumTab[i].size = readMotorolaWord(&ptr, &ptr_size); + if (ptr_size < 0) + { + setLastError("File too small"); + goto error_out; + } pDrumTab[i].repLen = pDrumTab[i].size; if (0x594d5432/*'YMT2'*/ == id) { - pDrumTab[i].repLen = readMotorolaWord(&ptr); // repLen - readMotorolaWord(&ptr); // flag + pDrumTab[i].repLen = readMotorolaWord(&ptr, &ptr_size); // repLen + readMotorolaWord(&ptr, &ptr_size); // flag + if (ptr_size < 0) + { + setLastError("File too small"); + goto error_out; + } } if (pDrumTab[i].repLen>pDrumTab[i].size) { @@ -454,13 +627,21 @@ if (pDrumTab[i].size) { + if (pDrumTab[i].size >= 0x80000000) + { + setLastError("Drumtab to big"); + goto error_out; + } + if (ptr_size<(ymint)pDrumTab[i].size) + { + setLastError("File too small"); + goto error_out; + } + pDrumTab[i].pData = (ymu8*)malloc(pDrumTab[i].size); memcpy(pDrumTab[i].pData,ptr,pDrumTab[i].size); ptr += pDrumTab[i].size; - } - else - { - pDrumTab[i].pData = NULL; + ptr_size -= pDrumTab[i].size; } } } @@ -477,18 +658,33 @@ pSongType = mstrdup("YM-T1"); } + if ((nbVoice > MAX_VOICE) || (nbVoice < 0)) + { + setLastError("Too many voices"); + goto error_out; + } + if ((nbFrame >= (ymint)(0x80000000 / (MAX_VOICE * (sizeof(ymTrackerLine_t))))) || (nbFrame < 0)) /* ymTrackerLine_t has a 2^N size */ + { + setLastError("Too many frames"); + goto error_out; + } + if (ptr_size < (ymint)(sizeof(ymTrackerLine_t) * nbVoice * nbFrame)) + { + setLastError("File too small"); + goto error_out; + } pDataStream = ptr; ymChip.setClock(ATARI_CLOCK); ymTrackerInit(100); // 80% de volume maxi. - streamInc = 16; + streamInc = 16; /* not needed, since this is only used for YMx formats */ setTimeControl(YMTRUE); pSongPlayer = mstrdup("Universal Tracker"); break; default: - setLastError("Unknow YM format !"); + setLastError("Unknown YM format !"); return YMFALSE; break; } @@ -499,6 +695,25 @@ } return YMTRUE; +error_out: + for (i=0;i0) + { + myFree((void **)&pDrumTab); + nbDrum=0; + } + myFree((void **)&pSongName); + myFree((void **)&pSongAuthor); + myFree((void **)&pSongComment); + myFree((void **)&pSongType); /* <- never needed, but we keep it for purity */ + myFree((void **)&pSongPlayer); /* <- never needed, but we keep it for purity */ + myFree((void **)&pMixBlock); + myFree((void **)&pBigSampleBuffer); /* <- never needed, but we keep it for purity */ + return YMFALSE; } @@ -646,12 +861,6 @@ return YMTRUE; } -void myFree(void **pPtr) -{ - if (*pPtr) free(*pPtr); - *pPtr = NULL; -} - void CYmMusic::unLoad(void) { diff -urN 12-STYMulator-0.21a_load_errors/src/stsoundlib/YmMusic.cpp 13-STYMulator-0.21a-fail_on_bogus_data/src/stsoundlib/YmMusic.cpp --- 12-STYMulator-0.21a_load_errors/src/stsoundlib/YmMusic.cpp 2010-04-25 12:10:25.281611853 +0200 +++ 13-STYMulator-0.21a-fail_on_bogus_data/src/stsoundlib/YmMusic.cpp 2010-04-22 10:03:20.472686871 +0200 @@ -368,11 +368,14 @@ if (ptr[12]) { - sampleFrq = (MFP_CLOCK / ptr[12]); - ymChip.drumStart( 2, // Voice C - sampleAdress[sampleNum], - sampleLen[sampleNum], - sampleFrq); + if (sampleNum < MAX_DIGIDRUM) + { + sampleFrq = (MFP_CLOCK / ptr[12]); + ymChip.drumStart( 2, // Voice C + sampleAdress[sampleNum], + sampleLen[sampleNum], + sampleFrq); + } } } } diff -urN 12-STYMulator-0.21a_load_errors/src/stsoundlib/YmMusic.h 13-STYMulator-0.21a-fail_on_bogus_data/src/stsoundlib/YmMusic.h --- 12-STYMulator-0.21a_load_errors/src/stsoundlib/YmMusic.h 2010-04-21 23:39:57.776202559 +0200 +++ 13-STYMulator-0.21a-fail_on_bogus_data/src/stsoundlib/YmMusic.h 2010-04-22 09:59:31.683687192 +0200 @@ -38,8 +38,6 @@ #include "Ymload.h" #include "digidrum.h" -#define MAX_DIGIDRUM 128 - #define YMTPREC 16 #define MAX_VOICE 8 #define PC_DAC_FREQ 44100