Skip to content

Commit 6efafba

Browse files
AliceLRsezero
authored andcommitted
Fix MT2 loader crashes and hangs found by libFuzzer.
* MT2: fix out-of-bounds reads due to missing nDrumDataLen check. * MT2: fix out-of-bounds reads due to missing pattern/track checks. * MT2: fix out-of-bounds reads due to broken/nonsensical instrument bounds checks. * MT2: fix out-of-bounds reads due to missing sample data length bounds check. * MT2: fix out-of-bounds reads due to bad checks on group structs. * MT2: fix hangs caused by overflows preventing the data chunk size bounds check from working. * MT2: constify pattern data pointer derived from lpStream. Konstanty#58
1 parent 8b7bac0 commit 6efafba

1 file changed

Lines changed: 23 additions & 14 deletions

File tree

src/load_mt2.cpp

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength)
211211
memcpy(m_szNames[0], pfh->szSongName, 32);
212212
m_szNames[0][31] = 0;
213213
dwMemPos = sizeof(MT2FILEHEADER);
214+
if (dwMemPos+2 > dwMemLength) return TRUE;
214215
nDrumDataLen = *(WORD *)(lpStream + dwMemPos);
215216
dwDrumDataPos = dwMemPos + 2;
216217
if (nDrumDataLen >= 2) pdd = (MT2DRUMSDATA *)(lpStream+dwDrumDataPos);
@@ -236,7 +237,7 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength)
236237
DWORD dwId = *(DWORD *)(lpStream+dwMemPos);
237238
DWORD dwLen = *(DWORD *)(lpStream+dwMemPos+4);
238239
dwMemPos += 8;
239-
if (dwMemPos + dwLen > dwMemLength) return TRUE;
240+
if (dwLen >= dwMemLength || dwMemPos > dwMemLength - dwLen) return TRUE;
240241
#ifdef MT2DEBUG
241242
CHAR s[5];
242243
memcpy(s, &dwId, 4);
@@ -274,7 +275,7 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength)
274275
const MT2PATTERN *pmp = (MT2PATTERN *)(lpStream+dwMemPos);
275276
UINT wDataLen = (pmp->wDataLen + 1) & ~1;
276277
dwMemPos += 6;
277-
if (dwMemPos + wDataLen > dwMemLength) break;
278+
if (dwMemPos > dwMemLength - wDataLen || wDataLen > dwMemLength) break;
278279
UINT nLines = pmp->wLines;
279280
if ((iPat < MAX_PATTERNS) && (nLines > 0) && (nLines <= 256))
280281
{
@@ -288,7 +289,7 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength)
288289
UINT len = wDataLen;
289290
if (pfh->fulFlags & 1) // Packed Patterns
290291
{
291-
BYTE *p = (BYTE *)(lpStream+dwMemPos);
292+
const BYTE *p = lpStream+dwMemPos;
292293
UINT pos = 0, row=0, ch=0;
293294
while (pos < len)
294295
{
@@ -297,6 +298,7 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength)
297298
UINT rptcount = 0;
298299
if (infobyte == 0xff)
299300
{
301+
if (pos + 2 > len) break;
300302
rptcount = p[pos++];
301303
infobyte = p[pos++];
302304
#if 0
@@ -310,13 +312,13 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength)
310312
{
311313
UINT patpos = row*m_nChannels+ch;
312314
cmd.note = cmd.instr = cmd.vol = cmd.pan = cmd.fxcmd = cmd.fxparam1 = cmd.fxparam2 = 0;
313-
if (infobyte & 1) cmd.note = p[pos++];
314-
if (infobyte & 2) cmd.instr = p[pos++];
315-
if (infobyte & 4) cmd.vol = p[pos++];
316-
if (infobyte & 8) cmd.pan = p[pos++];
317-
if (infobyte & 16) cmd.fxcmd = p[pos++];
318-
if (infobyte & 32) cmd.fxparam1 = p[pos++];
319-
if (infobyte & 64) cmd.fxparam2 = p[pos++];
315+
if ((infobyte & 1) && (pos < len)) cmd.note = p[pos++];
316+
if ((infobyte & 2) && (pos < len)) cmd.instr = p[pos++];
317+
if ((infobyte & 4) && (pos < len)) cmd.vol = p[pos++];
318+
if ((infobyte & 8) && (pos < len)) cmd.pan = p[pos++];
319+
if ((infobyte & 16) && (pos < len)) cmd.fxcmd = p[pos++];
320+
if ((infobyte & 32) && (pos < len)) cmd.fxparam1 = p[pos++];
321+
if ((infobyte & 64) && (pos < len)) cmd.fxparam2 = p[pos++];
320322
#ifdef MT2DEBUG
321323
if (cmd.fxcmd)
322324
{
@@ -332,11 +334,12 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength)
332334
} else
333335
{
334336
const MT2COMMAND *p = (MT2COMMAND *)(lpStream+dwMemPos);
337+
UINT pos = 0;
335338
UINT n = 0;
336-
while ((len > sizeof(MT2COMMAND)) && (n < m_nChannels*nLines))
339+
while ((pos + sizeof(MT2COMMAND) <= len) && (n < m_nChannels*nLines))
337340
{
338341
ConvertMT2Command(this, m, p);
339-
len -= sizeof(MT2COMMAND);
342+
pos += sizeof(MT2COMMAND);
340343
n++;
341344
p++;
342345
m++;
@@ -419,8 +422,10 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength)
419422
#ifdef MT2DEBUG
420423
if (iIns <= pfh->wInstruments) Log(" Instrument #%d at offset %04X: %d bytes\n", iIns, dwMemPos, pmi->dwDataLen);
421424
#endif
422-
if (((LONG)pmi->dwDataLen > 0) && (dwMemPos <= dwMemLength - 40) && (pmi->dwDataLen <= dwMemLength - (dwMemPos + 40)))
425+
if (pmi->dwDataLen > dwMemLength - (dwMemPos+36)) return TRUE;
426+
if (pmi->dwDataLen > 0)
423427
{
428+
if (dwMemPos + sizeof(MT2INSTRUMENT) - 4 > dwMemLength) return TRUE;
424429
InstrMap[iIns-1] = pmi;
425430
if (penv)
426431
{
@@ -433,6 +438,7 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength)
433438
if (pfh->wVersion <= 0x201)
434439
{
435440
DWORD dwEnvPos = dwMemPos + sizeof(MT2INSTRUMENT) - 4;
441+
if (dwEnvPos + 2*sizeof(MT2ENVELOPE) > dwMemLength) return TRUE;
436442
pehdr[0] = (MT2ENVELOPE *)(lpStream+dwEnvPos);
437443
pehdr[1] = (MT2ENVELOPE *)(lpStream+dwEnvPos+8);
438444
pehdr[2] = pehdr[3] = NULL;
@@ -442,10 +448,12 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength)
442448
} else
443449
{
444450
DWORD dwEnvPos = dwMemPos + sizeof(MT2INSTRUMENT);
451+
if (dwEnvPos > dwMemLength) return TRUE;
445452
for (UINT i=0; i<4; i++)
446453
{
447454
if (pmi->wEnvFlags1 & (1<<i))
448455
{
456+
if (dwEnvPos + sizeof(MT2ENVELOPE) > dwMemLength) return TRUE;
449457
pehdr[i] = (MT2ENVELOPE *)(lpStream+dwEnvPos);
450458
pedata[i] = (WORD *)pehdr[i]->EnvData;
451459
dwEnvPos += sizeof(MT2ENVELOPE);
@@ -540,6 +548,7 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength)
540548
{
541549
memcpy(m_szNames[iSmp], pms->szName, 32);
542550
}
551+
if (pms->dwDataLen > dwMemLength - (dwMemPos+36)) return TRUE;
543552
if (pms->dwDataLen > 0)
544553
{
545554
SampleMap[iSmp-1] = pms;
@@ -573,12 +582,12 @@ BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength)
573582
#endif
574583
for (UINT iMap=0; iMap<255; iMap++) if (InstrMap[iMap])
575584
{
576-
if (dwMemPos+8 > dwMemLength) return TRUE;
577585
const MT2INSTRUMENT *pmi = InstrMap[iMap];
578586
INSTRUMENTHEADER *penv = NULL;
579587
if (iMap<m_nInstruments) penv = Headers[iMap+1];
580588
for (UINT iGrp=0; iGrp<pmi->wSamples; iGrp++)
581589
{
590+
if (dwMemPos+8 > dwMemLength) return TRUE;
582591
if (penv)
583592
{
584593
const MT2GROUP *pmg = (MT2GROUP *)(lpStream+dwMemPos);

0 commit comments

Comments
 (0)