@@ -87,11 +87,12 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength)
8787// ---------------------------------------------------------------
8888{
8989 const DMFHEADER *pfh = (DMFHEADER *)lpStream;
90- DMFINFO *psi;
91- DMFSEQU *sequ;
90+ const DMFINFO *psi;
91+ const DMFPATT *patt;
92+ const DMFSEQU *sequ;
9293 DWORD dwMemPos;
9394 BYTE infobyte[32 ];
94- BYTE smplflags[MAX_SAMPLES], hasSMPI = 0 ;
95+ BYTE smplflags[MAX_SAMPLES], hasSMPI = 0 , hasSMPD = 0 ;
9596
9697 if ((!lpStream) || (dwMemLength < 1024 )) return FALSE ;
9798 if ((pfh->id != 0x464d4444 ) || (!pfh->version ) || (pfh->version & 0xF0 )) return FALSE ;
@@ -115,7 +116,7 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength)
115116 case 0x47534d43 :
116117 psi = (DMFINFO *)(lpStream+dwMemPos);
117118 if (id == 0x47534d43 ) dwMemPos++;
118- if ((psi->infosize > dwMemLength) || (psi-> infosize + dwMemPos + 8 > dwMemLength)) goto dmfexit;
119+ if ((psi->infosize > dwMemLength) || (dwMemPos + 8 > dwMemLength - psi-> infosize )) goto dmfexit;
119120 if ((psi->infosize >= 8 ) && (!m_lpszSongComments))
120121 {
121122 m_lpszSongComments = new char [psi->infosize ]; // changed from CHAR
@@ -138,9 +139,10 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength)
138139 // "SEQU"
139140 case 0x55514553 :
140141 sequ = (DMFSEQU *)(lpStream+dwMemPos);
141- if ((sequ->seqsize >= dwMemLength) || (dwMemPos + sequ->seqsize + 12 > dwMemLength)) goto dmfexit;
142+ if ((sequ->seqsize >= dwMemLength) || (dwMemPos + 8 > dwMemLength - sequ->seqsize )) goto dmfexit;
143+ if (sequ->seqsize >= 4 )
142144 {
143- UINT nseq = sequ->seqsize >> 1 ;
145+ UINT nseq = ( sequ->seqsize - 4 ) >> 1 ;
144146 if (nseq >= MAX_ORDERS-1 ) nseq = MAX_ORDERS-1 ;
145147 if (sequ->loopstart < nseq) m_nRestartPos = sequ->loopstart ;
146148 for (UINT i=0 ; i<nseq; i++) Order[i] = (BYTE)sequ->sequ [i];
@@ -150,12 +152,12 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength)
150152
151153 // "PATT"
152154 case 0x54544150 :
153- if (!m_nChannels)
155+ patt = (DMFPATT *)(lpStream+dwMemPos);
156+ if ((patt->patsize >= dwMemLength) || (dwMemPos + 8 > dwMemLength - patt->patsize )) goto dmfexit;
157+ if (patt->patsize >= 4 && !m_nChannels)
154158 {
155- DMFPATT *patt = (DMFPATT *)(lpStream+dwMemPos);
156159 UINT numpat;
157160 DWORD dwPos = dwMemPos + 11 ;
158- if ((patt->patsize >= dwMemLength) || (dwMemPos + patt->patsize + 8 > dwMemLength)) goto dmfexit;
159161 numpat = patt->numpat ;
160162 if (numpat > MAX_PATTERNS) numpat = MAX_PATTERNS;
161163 m_nChannels = patt->tracks ;
@@ -164,7 +166,8 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength)
164166 if (m_nChannels < 4 ) m_nChannels = 4 ;
165167 for (UINT npat=0 ; npat<numpat; npat++)
166168 {
167- DMFTRACK *pt = (DMFTRACK *)(lpStream+dwPos);
169+ const DMFTRACK *pt = (DMFTRACK *)(lpStream+dwPos);
170+ if (dwPos + 8 >= dwMemLength) break ;
168171 #ifdef DMFLOG
169172 Log (" Pattern #%d: %d tracks, %d rows\n " , npat, pt->tracks , pt->ticks );
170173 #endif
@@ -174,7 +177,7 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength)
174177 if (ticks > 256 ) ticks = 256 ;
175178 if (ticks < 16 ) ticks = 16 ;
176179 dwPos += 8 ;
177- if ((pt->jmpsize >= dwMemLength) || (dwPos + pt-> jmpsize + 4 >= dwMemLength)) break ;
180+ if ((pt->jmpsize >= dwMemLength) || (dwPos + 4 > dwMemLength - pt-> jmpsize )) break ;
178181 PatternSize[npat] = (WORD)ticks;
179182 MODCOMMAND *m = AllocatePattern (PatternSize[npat], m_nChannels);
180183 if (!m) goto dmfexit;
@@ -193,6 +196,7 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength)
193196 // Parse track global effects
194197 if (!glbinfobyte)
195198 {
199+ if (d+1 > dwPos) break ;
196200 BYTE info = lpStream[d++];
197201 BYTE infoval = 0 ;
198202 if ((info & 0x80 ) && (d < dwPos)) glbinfobyte = lpStream[d++];
@@ -214,30 +218,40 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength)
214218 // Parse channels
215219 for (UINT i=0 ; i<tracks; i++) if (!infobyte[i])
216220 {
221+ if (d+1 > dwPos) break ;
217222 MODCOMMAND cmd = {0 ,0 ,0 ,0 ,0 ,0 };
218223 BYTE info = lpStream[d++];
219- if (info & 0x80 ) infobyte[i] = lpStream[d++];
224+ if (info & 0x80 )
225+ {
226+ if (d+1 > dwPos) break ;
227+ infobyte[i] = lpStream[d++];
228+ }
220229 // Instrument
221230 if (info & 0x40 )
222231 {
232+ if (d+1 > dwPos) break ;
223233 cmd.instr = lpStream[d++];
224234 }
225235 // Note
226236 if (info & 0x20 )
227237 {
238+ if (d+1 > dwPos) break ;
228239 cmd.note = lpStream[d++];
229240 if ((cmd.note ) && (cmd.note < 0xfe )) cmd.note &= 0x7f ;
230241 if ((cmd.note ) && (cmd.note < 128 )) cmd.note += 24 ;
231242 }
232243 // Volume
233244 if (info & 0x10 )
234245 {
246+ if (d+1 > dwPos) break ;
235247 cmd.volcmd = VOLCMD_VOLUME;
236248 cmd.vol = (lpStream[d++]+3 )>>2 ;
237249 }
238250 // Effect 1
239251 if (info & 0x08 )
240252 {
253+ if (d+2 > dwPos) break ;
254+
241255 BYTE efx = lpStream[d++];
242256 BYTE eval = lpStream[d++];
243257 switch (efx)
@@ -259,6 +273,8 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength)
259273 // Effect 2
260274 if (info & 0x04 )
261275 {
276+ if (d+2 > dwPos) break ;
277+
262278 BYTE efx = lpStream[d++];
263279 BYTE eval = lpStream[d++];
264280 switch (efx)
@@ -289,6 +305,8 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength)
289305 // Effect 3
290306 if (info & 0x02 )
291307 {
308+ if (d+2 > dwPos) break ;
309+
292310 BYTE efx = lpStream[d++];
293311 BYTE eval = lpStream[d++];
294312 switch (efx)
@@ -372,22 +390,24 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength)
372390 #endif
373391 if (dwPos + 8 >= dwMemLength) break ;
374392 }
375- dwMemPos += patt->patsize + 8 ;
376393 }
394+ dwMemPos += patt->patsize + 8 ;
377395 break ;
378396
379397 // "SMPI": Sample Info
380398 case 0x49504d53 :
381399 {
382400 hasSMPI = 1 ;
383- DMFSMPI *pds = (DMFSMPI *)(lpStream+dwMemPos);
384- if (pds->size <= dwMemLength - dwMemPos)
401+ const DMFSMPI *pds = (DMFSMPI *)(lpStream+dwMemPos);
402+ if ((pds->size >= dwMemLength) || (dwMemPos + 8 > dwMemLength - pds->size )) goto dmfexit;
403+ if (pds->size >= 1 )
385404 {
386405 DWORD dwPos = dwMemPos + 9 ;
387406 m_nSamples = pds->samples ;
388407 if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1 ;
389408 for (UINT iSmp=1 ; iSmp<=m_nSamples; iSmp++)
390409 {
410+ if (dwPos >= dwMemPos + pds->size + 8 ) break ;
391411 UINT namelen = lpStream[dwPos];
392412 smplflags[iSmp] = 0 ;
393413 if (dwPos+namelen+1 +sizeof (DMFSAMPLE) > dwMemPos+pds->size +8 ) break ;
@@ -398,7 +418,7 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength)
398418 m_szNames[iSmp][rlen] = 0 ;
399419 }
400420 dwPos += namelen + 1 ;
401- DMFSAMPLE *psh = (DMFSAMPLE *)(lpStream+dwPos);
421+ const DMFSAMPLE *psh = (DMFSAMPLE *)(lpStream+dwPos);
402422 MODINSTRUMENT *psmp = &Ins[iSmp];
403423 psmp->nLength = psh->len ;
404424 psmp->nLoopStart = psh->loopstart ;
@@ -425,7 +445,7 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength)
425445 {
426446 DWORD dwPos = dwMemPos + 8 ;
427447 UINT ismpd = 0 ;
428- for (UINT iSmp=1 ; iSmp<=m_nSamples; iSmp++)
448+ for (UINT iSmp=1 ; iSmp<=m_nSamples && !hasSMPD ; iSmp++)
429449 {
430450 ismpd++;
431451 DWORD pksize;
@@ -458,6 +478,7 @@ BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength)
458478 }
459479 dwPos += pksize;
460480 }
481+ hasSMPD = 1 ;
461482 dwMemPos = dwPos;
462483 }
463484 break ;
@@ -520,8 +541,8 @@ static BYTE DMFReadBits(DMF_HTREE *tree, UINT nbits)
520541 {
521542 tree->bitnum --;
522543 } else
523- {
524- tree->bitbuf = (tree-> ibuf < tree-> ibufmax ) ? *(tree->ibuf ++) : 0 ;
544+ if (tree-> ibuf < tree-> ibufmax ) {
545+ tree->bitbuf = *(tree->ibuf ++);
525546 tree->bitnum = 7 ;
526547 }
527548 if (tree->bitbuf & 1 ) x |= bitv;
@@ -576,14 +597,24 @@ int DMFUnpack(LPBYTE psample, LPBYTE ibuf, LPBYTE ibufmax, UINT maxlen)
576597 DMF_HTREE tree;
577598 UINT actnode;
578599 BYTE value, sign, delta = 0 ;
579-
600+
580601 memset (&tree, 0 , sizeof (tree));
581602 tree.ibuf = ibuf;
582603 tree.ibufmax = ibufmax;
583604 DMFNewNode (&tree);
584605 value = 0 ;
606+
607+ if (tree.ibuf >= ibufmax) return tree.ibuf - ibuf;
608+
585609 for (UINT i=0 ; i<maxlen; i++)
586610 {
611+ if ((tree.ibuf >= tree.ibufmax ) && (!tree.bitnum ))
612+ {
613+ #ifdef DMFLOG
614+ Log (" DMFUnpack: unexpected EOF at output byte %d / %d\n " , i, maxlen);
615+ #endif
616+ break ;
617+ }
587618 actnode = 0 ;
588619 sign = DMFReadBits (&tree, 1 );
589620 do
0 commit comments