Skip to content

Commit f00a287

Browse files
authored
Merge pull request #76 from AliceLR/cleanup-66-3
Fix MIDI issues from the fuzz-patch-1/oob_read_fixes merge.
2 parents 8e781b4 + 96cf6ee commit f00a287

File tree

1 file changed

+55
-103
lines changed

1 file changed

+55
-103
lines changed

src/load_mid.cpp

Lines changed: 55 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -101,75 +101,14 @@ typedef struct _MIDTRACK
101101
#define _mm_recalloc(h,buf,sz,elsz) realloc(buf,sz)
102102
#define _mm_free(h,p) free(p)
103103

104-
typedef struct {
105-
char *mm;
106-
unsigned int sz;
107-
int pos;
108-
int err;
109-
} MMFILE;
110-
111-
static void mmfseek(MMFILE *mmfile, long p, int whence)
112-
{
113-
switch(whence) {
114-
case SEEK_SET:
115-
mmfile->pos = p;
116-
break;
117-
case SEEK_CUR:
118-
mmfile->pos += p;
119-
break;
120-
case SEEK_END:
121-
mmfile->pos = mmfile->sz + p;
122-
break;
123-
}
124-
}
125-
126-
static long mmftell(MMFILE *mmfile)
127-
{
128-
return mmfile->pos;
129-
}
130-
131-
static BYTE mmreadUBYTE(MMFILE *mmfile)
132-
{
133-
BYTE b;
134-
if ((unsigned int)mmfile->pos >= mmfile->sz)
135-
{
136-
mmfile->err = EOF;
137-
return 0;
138-
}
139-
b = (BYTE)mmfile->mm[mmfile->pos];
140-
mmfile->pos++;
141-
return b;
142-
}
143-
144-
static unsigned long mmreadUBYTES(BYTE *buf, unsigned long sz, MMFILE *mmfile)
145-
{
146-
if ((unsigned long)mmfile->pos + sz >= mmfile->sz)
147-
{
148-
mmfile->err = EOF;
149-
return 0;
150-
}
151-
memcpy(buf, &mmfile->mm[mmfile->pos], sz);
152-
mmfile->pos += sz;
153-
return sz;
154-
}
155-
156-
static unsigned long mmreadSBYTES(char *buf, long sz, MMFILE *mmfile)
157-
{
158-
if ((unsigned long)mmfile->pos + sz >= mmfile->sz)
159-
{
160-
mmfile->err = EOF;
161-
return 0;
162-
}
163-
memcpy(buf, &mmfile->mm[mmfile->pos], sz);
164-
mmfile->pos += sz;
165-
return sz;
166-
}
167-
168104
/**********************************************************************/
169105

170106
typedef struct _MIDHANDLE
171107
{
172-
MMFILE *mmf;
108+
const BYTE *mm;
109+
unsigned long sz;
110+
unsigned long pos;
111+
int err;
173112
MIDTRACK *track;
174113
MIDTRACK *tp;
175114
ULONG tracktime;
@@ -738,26 +677,46 @@ static void mid_add_pitchwheel(MIDHANDLE *h, int mch, int wheel)
738677

739678
static uint32_t mid_read_long(MIDHANDLE *h)
740679
{
741-
BYTE buf[4] = {0,0,0,0};
742-
if (h->mmf->pos < h->mmf->sz - 4)
743-
mmreadUBYTES(buf, 4, h->mmf);
680+
BYTE buf[4];
681+
if (h->pos > h->sz - 4) {
682+
h->err = EOF;
683+
return 0;
684+
}
685+
memcpy(buf, h->mm + h->pos, 4);
686+
h->pos += 4;
744687
return (buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|buf[3];
745688
}
746689

747690
static short int mid_read_short(MIDHANDLE *h)
748691
{
749-
BYTE buf[2] = {0,0};
750-
if (h->mmf->pos < h->mmf->sz - 2)
751-
mmreadUBYTES(buf, 2, h->mmf);
692+
BYTE buf[2];
693+
if (h->pos > h->sz - 2) {
694+
h->err = EOF;
695+
return 0;
696+
}
697+
memcpy(buf, h->mm + h->pos, 2);
698+
h->pos += 2;
752699
return (buf[0]<<8)|buf[1];
753700
}
754701

755702
static BYTE mid_read_byte(MIDHANDLE *h)
756703
{
757-
if (h->mmf->pos < h->mmf->sz - 1)
758-
return mmreadUBYTE(h->mmf);
759-
else
704+
if (h->pos >= h->sz) {
705+
h->err = EOF;
706+
return 0;
707+
}
708+
return h->mm[h->pos++];
709+
}
710+
711+
static unsigned long mid_read_bytes(void *dest, unsigned long sz, MIDHANDLE *h)
712+
{
713+
if (sz > h->sz || h->pos > h->sz - sz) {
714+
h->err = EOF;
760715
return 0;
716+
}
717+
memcpy(dest, h->mm + h->pos, sz);
718+
h->pos += sz;
719+
return sz;
761720
}
762721

763722
static int mid_read_delta(MIDHANDLE *h)
@@ -782,14 +741,12 @@ BOOL CSoundFile::TestMID(const BYTE *lpStream, DWORD dwMemLength)
782741
{
783742
char id[5];
784743
MIDHANDLE h;
785-
MMFILE mm;
786744
if (dwMemLength < 14) return FALSE;
787-
mm.mm = (char *)lpStream;
788-
mm.sz = dwMemLength;
789-
mm.err = 0;
790-
h.mmf = &mm;
791-
mmfseek(h.mmf,0,SEEK_SET);
792-
mmreadSBYTES(id, 4, h.mmf);
745+
h.mm = lpStream;
746+
h.sz = dwMemLength;
747+
h.pos = 0;
748+
h.err = 0;
749+
mid_read_bytes(id, 4, &h);
793750
id[4] = '\0';
794751
return !strcmp(id,"MThd") && mid_read_long(&h) == 6;
795752
}
@@ -1197,7 +1154,6 @@ BOOL CSoundFile::ReadMID(const BYTE *lpStream, DWORD dwMemLength)
11971154
{
11981155
static int avoid_reentry = 0;
11991156
MIDHANDLE *h;
1200-
MMFILE mm;
12011157
int ch, dmulti, maxtempo, panlow, panhigh, numchans, numtracks;
12021158
MIDTRACK *ttp;
12031159
uint32_t t, numpats;
@@ -1213,23 +1169,21 @@ BOOL CSoundFile::ReadMID(const BYTE *lpStream, DWORD dwMemLength)
12131169
if( !TestMID(lpStream, dwMemLength) ) goto ErrorExit;
12141170
h = MID_Init();
12151171
if( !h ) goto ErrorExit;
1216-
h->mmf = &mm;
1217-
mm.mm = (char *)lpStream;
1218-
mm.sz = dwMemLength;
1219-
mm.pos = 0;
1220-
mm.err = 0;
1172+
h->mm = lpStream;
1173+
h->sz = dwMemLength;
1174+
h->err = 0;
12211175
h->debug = getenv(ENV_MMMID_DEBUG);
12221176
h->verbose = getenv(ENV_MMMID_VERBOSE);
12231177
pat_resetsmp();
12241178
pat_init_patnames();
12251179

1226-
mmfseek(h->mmf,8,SEEK_SET);
1227-
h->midiformat = mid_read_short(h);
1180+
h->pos = 8;
1181+
h->midiformat = mid_read_short(h);
12281182
h->miditracks = mid_read_short(h);
12291183
h->resolution = mid_read_short(h);
1230-
if (mm.err) goto ErrorCleanup;
1184+
if (h->err) goto ErrorCleanup;
12311185

1232-
// at this point the h->mmf is positioned at first miditrack
1186+
// at this point the h->pos is positioned at first miditrack
12331187
if( h->midiformat == 0 ) h->miditracks = 1;
12341188
if( h->resolution & 0x8000 )
12351189
h->divider = ((h->resolution & 0x7f00)>>8)*(h->resolution & 0xff);
@@ -1280,9 +1234,7 @@ BOOL CSoundFile::ReadMID(const BYTE *lpStream, DWORD dwMemLength)
12801234
}
12811235
for( t=0; t<(uint32_t)h->miditracks; t++ ) {
12821236
if( h->verbose ) printf("Parsing track %d\n", t+1);
1283-
if (h->mmf->pos < dwMemLength - 4) {
1284-
mmreadSBYTES(buf,4,h->mmf);
1285-
} else {
1237+
if (mid_read_bytes(buf,4,h) < 4) {
12861238
buf[0] = '\0'; // make sure start is \0
12871239
}
12881240
buf[4] = '\0';
@@ -1291,11 +1243,11 @@ BOOL CSoundFile::ReadMID(const BYTE *lpStream, DWORD dwMemLength)
12911243
goto ErrorCleanup;
12921244
}
12931245
miditracklen = mid_read_long(h);
1294-
if (mm.err || mm.sz < miditracklen) continue;
1246+
if (h->err || h->sz < miditracklen) continue;
12951247
runningstatus = 0;
12961248
if( t && h->midiformat == 1 ) mid_rewind_tracks(h); // tracks sound simultaneously
12971249
while( miditracklen > 0 ) {
1298-
if (mm.err) break;
1250+
if (h->err) break;
12991251
miditracklen -= mid_read_delta(h);
13001252
midibyte[0] = mid_read_byte(h);
13011253
miditracklen--;
@@ -1414,7 +1366,7 @@ BOOL CSoundFile::ReadMID(const BYTE *lpStream, DWORD dwMemLength)
14141366
t, (long)(h->tracktime), midibyte[0]);
14151367
while( midibyte[0] != 0xf7 ) {
14161368
midibyte[0] = mid_read_byte(h);
1417-
if (mm.err) break;
1369+
if (h->err) break;
14181370
miditracklen--;
14191371
if( h->debug ) printf(" %02X", midibyte[0]);
14201372
}
@@ -1436,7 +1388,7 @@ BOOL CSoundFile::ReadMID(const BYTE *lpStream, DWORD dwMemLength)
14361388
t, (long)(h->tracktime), metalen);
14371389
while( metalen > 0 ) {
14381390
midibyte[1] = mid_read_byte(h);
1439-
if (mm.err) break;
1391+
if (h->err) break;
14401392
metalen--;
14411393
miditracklen--;
14421394
if( h->debug ) printf(" %02X", midibyte[1]);
@@ -1449,14 +1401,14 @@ BOOL CSoundFile::ReadMID(const BYTE *lpStream, DWORD dwMemLength)
14491401
metalen = h->deltatime;
14501402
if( metalen > 31 ) metalen = 31;
14511403
if( metalen ) {
1452-
if (!mmreadSBYTES(buf, metalen, h->mmf)) break;
1404+
if (!mid_read_bytes(buf, metalen, h)) break;
14531405
miditracklen -= metalen;
14541406
}
14551407
buf[metalen] = '\0';
14561408
metalen = h->deltatime - metalen;
14571409
while( metalen > 0 ) {
14581410
midibyte[1] = mid_read_byte(h);
1459-
if (mm.err) break;
1411+
if (h->err) break;
14601412
metalen--;
14611413
miditracklen--;
14621414
}
@@ -1505,16 +1457,16 @@ BOOL CSoundFile::ReadMID(const BYTE *lpStream, DWORD dwMemLength)
15051457
break;
15061458
}
15071459
if( miditracklen < 1 && (runningstatus != 0xff || midibyte[0] != 0x2f) ) {
1508-
delta = mmftell(h->mmf);
1509-
if (!mmreadSBYTES(buf,4,h->mmf)) break;
1460+
delta = h->pos;
1461+
if (!mid_read_bytes(buf,4,h)) break;
15101462
buf[4] = '\0';
15111463
if( strcmp(buf,"MTrk") ) {
15121464
miditracklen = 0x7fffffff;
15131465
mid_message("Meta event not at end of track, %s bytes left in track", "superfluous");
15141466
}
15151467
else
15161468
mid_message("Meta event not at end of track, %s bytes left in track", "no");
1517-
mmfseek(h->mmf,delta,SEEK_SET);
1469+
h->pos = delta;
15181470
}
15191471
}
15201472
}

0 commit comments

Comments
 (0)