Skip to content

Commit 8b7bac0

Browse files
AliceLRsezero
authored andcommitted
Fix MDL loader crash bugs found by libFuzzer.
* MDL: fix out-of-bounds reads due to missing info chunk bounds check. * MDL: fix out-of-bounds reads due to a missing bounds check when loading instruments. * MDL: fix out-of-bounds reads and other bugs due to bad envelope bounding and missing duplicate envelope chunk checks. * MDL: fix out-of-bounds reads due to broken track bounds checks. Konstanty#58
1 parent 3e1ff74 commit 8b7bac0

File tree

1 file changed

+11
-9
lines changed

1 file changed

+11
-9
lines changed

src/load_mdl.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ BOOL CSoundFile::ReadMDL(const BYTE *lpStream, DWORD dwMemLength)
216216
m_szNames[0][31] = 0;
217217
norders = pmib->norders;
218218
if (norders > MAX_ORDERS) norders = MAX_ORDERS;
219+
if (blocklen < sizeof(MDLINFOBLOCK) + norders - sizeof(pmib->seq)) return FALSE;
219220
m_nRestartPos = pmib->repeatpos;
220221
m_nDefaultGlobalVolume = pmib->globalvol;
221222
m_nDefaultTempo = pmib->tempo;
@@ -286,7 +287,7 @@ BOOL CSoundFile::ReadMDL(const BYTE *lpStream, DWORD dwMemLength)
286287
case 0x4949:
287288
ninstruments = lpStream[dwMemPos];
288289
dwPos = dwMemPos+1;
289-
for (i=0; i<ninstruments; i++)
290+
for (i=0; dwPos+34<dwMemLength && i<ninstruments; i++)
290291
{
291292
UINT nins = lpStream[dwPos];
292293
if ((nins >= MAX_INSTRUMENTS) || (!nins)) break;
@@ -300,6 +301,7 @@ BOOL CSoundFile::ReadMDL(const BYTE *lpStream, DWORD dwMemLength)
300301
memcpy(penv->name, lpStream+dwPos+2, 32);
301302
penv->nGlobalVol = 64;
302303
penv->nPPC = 5*12;
304+
if (34 + 14u*lpStream[dwPos+1] > dwMemLength - dwPos) break;
303305
for (j=0; j<lpStream[dwPos+1]; j++)
304306
{
305307
const BYTE *ps = lpStream+dwPos+34+14*j;
@@ -345,18 +347,18 @@ BOOL CSoundFile::ReadMDL(const BYTE *lpStream, DWORD dwMemLength)
345347
break;
346348
// VE: Volume Envelope
347349
case 0x4556:
348-
if ((nvolenv = lpStream[dwMemPos]) == 0) break;
349-
if (dwMemPos + nvolenv*32 + 1 <= dwMemLength) pvolenv = lpStream + dwMemPos + 1;
350+
if (nvolenv || (nvolenv = lpStream[dwMemPos]) == 0) break;
351+
if (dwMemPos + nvolenv*33 + 1 <= dwMemLength) pvolenv = lpStream + dwMemPos + 1;
350352
break;
351353
// PE: Panning Envelope
352354
case 0x4550:
353-
if ((npanenv = lpStream[dwMemPos]) == 0) break;
354-
if (dwMemPos + npanenv*32 + 1 <= dwMemLength) ppanenv = lpStream + dwMemPos + 1;
355+
if (npanenv || (npanenv = lpStream[dwMemPos]) == 0) break;
356+
if (dwMemPos + npanenv*33 + 1 <= dwMemLength) ppanenv = lpStream + dwMemPos + 1;
355357
break;
356358
// FE: Pitch Envelope
357359
case 0x4546:
358-
if ((npitchenv = lpStream[dwMemPos]) == 0) break;
359-
if (dwMemPos + npitchenv*32 + 1 <= dwMemLength) ppitchenv = lpStream + dwMemPos + 1;
360+
if (npitchenv || (npitchenv = lpStream[dwMemPos]) == 0) break;
361+
if (dwMemPos + npitchenv*33 + 1 <= dwMemLength) ppitchenv = lpStream + dwMemPos + 1;
360362
break;
361363
// IS: Sample Infoblock
362364
case 0x5349:
@@ -437,14 +439,14 @@ BOOL CSoundFile::ReadMDL(const BYTE *lpStream, DWORD dwMemLength)
437439
UINT nTrack = patterntracks[ipat*32+chn];
438440

439441
lpTracks += 2;
440-
for (UINT ntrk=1; ntrk<nTrack && lpTracks < (dwMemLength + lpStream - len); ntrk++)
442+
for (UINT ntrk=1; ntrk<nTrack && lpTracks + 1 < (dwMemLength + lpStream - len); ntrk++)
441443
{
442444
lpTracks += len;
443445
len = lpTracks[0] | (lpTracks[1] << 8);
444446
lpTracks += 2;
445447
}
446448

447-
if ( len > dwMemLength - dwTrackPos ) len = 0;
449+
if ( len > dwMemLength - (lpTracks - lpStream) ) len = 0;
448450

449451
UnpackMDLTrack(m, m_nChannels, PatternSize[ipat], nTrack, lpTracks, len);
450452
}

0 commit comments

Comments
 (0)