Skip to content

Commit 96cf6ee

Browse files
committed
Fix MIDI issues from the fuzz-patch-1/oob_read_fixes merge.
The merge between these patches broke some important hang fixes in fuzz-patch-1. There weren't any particularly good options for reconciling these, but the least bad one seemed to be getting rid of the unnecessary extra IO abstraction and moving the EOF state flag to the mid_read_* functions. Also fixes a -Wsign-compare warning at (former) line 1294.
1 parent 8e781b4 commit 96cf6ee

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)