dependencies/SDL_sound/libmodplug/load_xm.c in gosu-1.3.0 vs dependencies/SDL_sound/libmodplug/load_xm.c in gosu-1.4.0

- old
+ new

@@ -8,11 +8,11 @@ #include "libmodplug.h" //////////////////////////////////////////////////////// // FastTracker II XM file support -#ifdef MSC_VER +#ifdef _MSC_VER #pragma warning(disable:4244) #endif #pragma pack(1) typedef struct tagXMFILEHEADER @@ -27,21 +27,19 @@ WORD speed; WORD tempo; BYTE order[256]; } XMFILEHEADER; - typedef struct tagXMINSTRUMENTHEADER { DWORD size; CHAR name[22]; BYTE type; BYTE samples; BYTE samplesh; } XMINSTRUMENTHEADER; - typedef struct tagXMSAMPLEHEADER { DWORD shsize; BYTE snum[96]; WORD venv[24]; @@ -68,11 +66,10 @@ BYTE res; char name[22]; } XMSAMPLESTRUCT; #pragma pack() - BOOL CSoundFile_ReadXM(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLength) //-------------------------------------------------------------- { XMSAMPLEHEADER xmsh; XMSAMPLESTRUCT xmss; @@ -86,18 +83,20 @@ UINT unused_samples; XMFILEHEADER xmhead; _this->m_nChannels = 0; if ((!lpStream) || (dwMemLength < 0x200)) return FALSE; - if (SDL_strncasecmp((LPCSTR)lpStream, "Extended Module", 15)) return FALSE; + if (SDL_strncmp((LPCSTR)lpStream, "Extended Module:", 16)) return FALSE; SDL_memcpy(&xmhead, lpStream+60, sizeof (xmhead)); dwHdrSize = bswapLE32(xmhead.size); norders = bswapLE16(xmhead.norder); - if ((!norders) || (norders > MAX_ORDERS)) return FALSE; restartpos = bswapLE16(xmhead.restartpos); channels = bswapLE16(xmhead.channels); + + if ((!dwHdrSize) || dwHdrSize > dwMemLength - 60) return FALSE; + if ((!norders) || (norders > MAX_ORDERS)) return FALSE; if ((!channels) || (channels > 64)) return FALSE; _this->m_nType = MOD_TYPE_XM; _this->m_nMinPeriod = 27; _this->m_nMaxPeriod = 54784; _this->m_nChannels = channels; @@ -160,10 +159,11 @@ { if (dwMemPos + 4 >= dwMemLength) break; dwMemPos++; dwSize = bswapLE32(*((DWORD *)(lpStream+dwMemPos))); } + if (dwMemPos + 9 > dwMemLength) return TRUE; rows = bswapLE16(*((WORD *)(lpStream+dwMemPos+5))); if ((!rows) || (rows > 256)) rows = 64; packsize = bswapLE16(*((WORD *)(lpStream+dwMemPos+7))); if (dwMemPos + dwSize + 4 > dwMemLength) return TRUE; dwMemPos += dwSize; @@ -186,17 +186,18 @@ { BYTE b = src[j++]; 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) && j < packsize) p->note = src[j++]; + if ((b & 2) && j < packsize) p->instr = src[j++]; + if ((b & 4) && j < packsize) vol = src[j++]; + if ((b & 8) && j < packsize) p->command = src[j++]; + if ((b & 16) && j < packsize) p->param = src[j++]; } else { + if (j + 5 > packsize) break; p->note = b; p->instr = src[j++]; vol = src[j++]; p->command = src[j++]; p->param = src[j++]; @@ -274,31 +275,32 @@ XMINSTRUMENTHEADER *pih; BYTE flags[32]; 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; - if ((_this->Headers[iIns] = (INSTRUMENTHEADER *) SDL_malloc(sizeof (INSTRUMENTHEADER))) == NULL) continue; - SDL_memset(_this->Headers[iIns], 0, sizeof(INSTRUMENTHEADER)); + pihlen = bswapLE32(pih->size); + if (pihlen >= dwMemLength || dwMemPos > dwMemLength - pihlen) return TRUE; + if ((_this->Headers[iIns] = (INSTRUMENTHEADER *) SDL_calloc(1, sizeof(INSTRUMENTHEADER))) == NULL) continue; if ((nsamples = pih->samples) > 0) { - if (dwMemPos + sizeof(XMSAMPLEHEADER) > dwMemLength) return TRUE; + if (dwMemPos + sizeof(XMINSTRUMENTHEADER) + sizeof(XMSAMPLEHEADER) > dwMemLength) return TRUE; SDL_memcpy(&xmsh, lpStream+dwMemPos+sizeof(XMINSTRUMENTHEADER), sizeof(XMSAMPLEHEADER)); xmsh.shsize = bswapLE32(xmsh.shsize); for (int i = 0; i < 24; ++i) { xmsh.venv[i] = bswapLE16(xmsh.venv[i]); xmsh.penv[i] = bswapLE16(xmsh.penv[i]); } 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; } SDL_memset(samplemap, 0, sizeof(samplemap)); if (nsamples > 32) return TRUE; @@ -429,11 +431,11 @@ } // Reading samples for (UINT ins=0; ins<nsamples; ins++) { if ((dwMemPos + sizeof(xmss) > dwMemLength) - || (dwMemPos + xmsh.shsize > dwMemLength)) return TRUE; + || (xmsh.shsize >= dwMemLength) || (dwMemPos > dwMemLength - xmsh.shsize)) return TRUE; SDL_memcpy(&xmss, lpStream+dwMemPos, sizeof(xmss)); xmss.samplen = bswapLE32(xmss.samplen); xmss.loopstart = bswapLE32(xmss.loopstart); xmss.looplen = bswapLE32(xmss.looplen); dwMemPos += xmsh.shsize; @@ -510,10 +512,11 @@ // Read midi config: "MIDI" if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4944494D)) { UINT len = *((DWORD *)(lpStream+dwMemPos+4)); dwMemPos += 8; + if (len >= dwMemLength || dwMemPos > dwMemLength - len) return TRUE; if (len == sizeof(MODMIDICFG)) { SDL_memcpy(&_this->m_MidiCfg, lpStream+dwMemPos, len); _this->m_dwSongFlags |= SONG_EMBEDMIDICFG; } @@ -521,11 +524,12 @@ // Read pattern names: "PNAM" if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e50)) { 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)) { _this->m_lpszPatternNames = (char *) SDL_malloc(len); if (_this->m_lpszPatternNames) { _this->m_nPatternNames = len / MAX_PATTERNNAME; @@ -537,11 +541,12 @@ // Read channel names: "CNAM" if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e43)) { 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) { dwMemPos += len; } } // Read mix plugins information @@ -549,6 +554,5 @@ { dwMemPos += CSoundFile_LoadMixPlugins(_this, lpStream+dwMemPos, dwMemLength-dwMemPos); } return TRUE; } -