Skip to content
Permalink
Browse files Browse the repository at this point in the history
Fix bug #175:
CVE-2017-11661, CVE-2017-11662, CVE-2017-11663, CVE-2017-11664:
Add a new size parameter to _WM_SetupMidiEvent() so that it
knows where to stop reading, and adjust its clients properly.
  • Loading branch information
sezero committed Aug 2, 2017
1 parent 84df184 commit ad6d7cf
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 40 deletions.
2 changes: 1 addition & 1 deletion include/internal_midi.h
Expand Up @@ -191,7 +191,7 @@ extern int _WM_midi_setup_divisions(struct _mdi *mdi, uint32_t divisions);

extern struct _mdi * _WM_initMDI(void);
extern void _WM_freeMDI(struct _mdi *mdi);
extern uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t running_event);
extern uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint32_t siz, uint8_t running_event);
extern void _WM_ResetToStart(struct _mdi *mdi);
extern void _WM_do_pan_adjust(struct _mdi *mdi, uint8_t ch);
extern void _WM_do_note_off_extra(struct _note *nte);
Expand Down
40 changes: 34 additions & 6 deletions src/f_hmi.c
Expand Up @@ -42,10 +42,10 @@ struct _mdi *
_WM_ParseNewHmi(uint8_t *hmi_data, uint32_t hmi_size) {
uint32_t hmi_tmp = 0;
uint8_t *hmi_base = hmi_data;
uint32_t data_siz;
uint16_t hmi_bpm = 0;
uint16_t hmi_division = 0;

// uint32_t hmi_duration_secs = 0;
uint32_t hmi_track_cnt = 0;
uint32_t *hmi_track_offset = NULL;
uint32_t i = 0;
Expand Down Expand Up @@ -74,8 +74,6 @@ _WM_ParseNewHmi(uint8_t *hmi_data, uint32_t hmi_size) {
uint8_t channel;
} *note;

//FIXME: This needs to be used for sanity check.
UNUSED(hmi_size);

if (memcmp(hmi_data, "HMI-MIDISONG061595", 18)) {
_WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_HMI, NULL, 0);
Expand Down Expand Up @@ -216,21 +214,35 @@ _WM_ParseNewHmi(uint8_t *hmi_data, uint32_t hmi_size) {
do {
hmi_data = hmi_base + hmi_track_offset[i];
hmi_delta[i] = 0;
if (hmi_track_offset[i] >= hmi_size) {
_WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_HMI, "file too short", 0);
goto _hmi_end;
}
data_siz = hmi_size - hmi_track_offset[i];

if (hmi_data[0] == 0xfe) {
// HMI only event of some sort.
if (hmi_data[1] == 0x10) {
hmi_tmp = (hmi_data[4] + 5);
hmi_data += hmi_tmp;
hmi_track_offset[i] += hmi_tmp;
hmi_tmp += 4;
} else if (hmi_data[1] == 0x15) {
hmi_data += 4;
hmi_track_offset[i] += 4;
hmi_tmp = 8;
} else {
hmi_tmp = 4;
}
hmi_data += 4;
hmi_track_offset[i] += 4;
if (hmi_tmp > data_siz) {
_WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_HMI, "file too short", 0);
goto _hmi_end;
}
data_siz -= hmi_tmp;
} else {
if ((setup_ret = _WM_SetupMidiEvent(hmi_mdi,hmi_data,hmi_running_event[i])) == 0) {
if ((setup_ret = _WM_SetupMidiEvent(hmi_mdi,hmi_data,data_siz,hmi_running_event[i])) == 0) {
goto _hmi_end;
}
if ((hmi_data[0] == 0xff) && (hmi_data[1] == 0x2f) && (hmi_data[2] == 0x00)) {
Expand Down Expand Up @@ -269,17 +281,25 @@ _WM_ParseNewHmi(uint8_t *hmi_data, uint32_t hmi_size) {

hmi_data += setup_ret;
hmi_track_offset[i] += setup_ret;
data_siz -= setup_ret;

note[hmi_tmp].length = 0;
if (*hmi_data > 0x7f) {
if (data_siz && *hmi_data > 0x7f) {
do {
if (!data_siz) break;
note[hmi_tmp].length = (note[hmi_tmp].length << 7) | (*hmi_data & 0x7F);
hmi_data++;
data_siz--;
hmi_track_offset[i]++;
} while (*hmi_data > 0x7F);
}
if (!data_siz) {
_WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_HMI, "file too short", 0);
goto _hmi_end;
}
note[hmi_tmp].length = (note[hmi_tmp].length << 7) | (*hmi_data & 0x7F);
hmi_data++;
data_siz--;
hmi_track_offset[i]++;

if (note[hmi_tmp].length) {
Expand All @@ -293,20 +313,28 @@ _WM_ParseNewHmi(uint8_t *hmi_data, uint32_t hmi_size) {
} else {
hmi_data += setup_ret;
hmi_track_offset[i] += setup_ret;
data_siz -= setup_ret;
}
}

// get track delta
// hmi_delta[i] = 0; // set at start of loop
if (*hmi_data > 0x7f) {
if (data_siz && *hmi_data > 0x7f) {
do {
if (!data_siz) break;
hmi_delta[i] = (hmi_delta[i] << 7) | (*hmi_data & 0x7F);
hmi_data++;
data_siz--;
hmi_track_offset[i]++;
} while (*hmi_data > 0x7F);
}
if (!data_siz) {
_WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_HMI, "file too short", 0);
goto _hmi_end;
}
hmi_delta[i] = (hmi_delta[i] << 7) | (*hmi_data & 0x7F);
hmi_data++;
data_siz--;
hmi_track_offset[i]++;
} while (!hmi_delta[i]);
if ((!smallest_delta) || (smallest_delta > hmi_delta[i])) {
Expand Down
15 changes: 13 additions & 2 deletions src/f_hmp.c
Expand Up @@ -235,6 +235,7 @@ _WM_ParseNewHmp(uint8_t *hmp_data, uint32_t hmp_size) {

// goto start of next chunk
hmp_data = hmp_chunk[i] + chunk_length[i];
chunk_length[i] -= chunk_ofs[i];
hmp_chunk[i] += chunk_ofs[i]++;
chunk_end[i] = 0;
}
Expand Down Expand Up @@ -273,17 +274,19 @@ _WM_ParseNewHmp(uint8_t *hmp_data, uint32_t hmp_size) {
// Reserved for loop markers
// TODO: still deciding what to do about these
hmp_chunk[i] += 3;
chunk_length[i] -= 3;
} else {
uint32_t setup_ret = 0;

if ((setup_ret = _WM_SetupMidiEvent(hmp_mdi, hmp_chunk[i], 0)) == 0) {
if ((setup_ret = _WM_SetupMidiEvent(hmp_mdi, hmp_chunk[i], chunk_length[i], 0)) == 0) {
goto _hmp_end;
}

if ((hmp_chunk[i][0] == 0xff) && (hmp_chunk[i][1] == 0x2f) && (hmp_chunk[i][2] == 0x00)) {
/* End of Chunk */
end_of_chunks++;
chunk_end[i] = 1;
chunk_length[i] -= 3;
hmp_chunk[i] += 3;
goto NEXT_CHUNK;
} else if ((hmp_chunk[i][0] == 0xff) && (hmp_chunk[i][1] == 0x51) && (hmp_chunk[i][2] == 0x03)) {
Expand All @@ -296,18 +299,26 @@ _WM_ParseNewHmp(uint8_t *hmp_data, uint32_t hmp_size) {
fprintf(stderr,"DEBUG: Tempo change %f\r\n", tempo_f);
}
hmp_chunk[i] += setup_ret;
chunk_length[i] -= setup_ret;
}
var_len_shift = 0;
chunk_delta[i] = 0;
if (*hmp_chunk[i] < 0x80) {
if (chunk_length[i] && *hmp_chunk[i] < 0x80) {
do {
if (! chunk_length[i]) break;
chunk_delta[i] = chunk_delta[i] + ((*hmp_chunk[i] & 0x7F) << var_len_shift);
var_len_shift += 7;
hmp_chunk[i]++;
chunk_length[i]--;
} while (*hmp_chunk[i] < 0x80);
}
if (! chunk_length[i]) {
_WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_HMP, "file too short", 0);
goto _hmp_end;
}
chunk_delta[i] = chunk_delta[i] + ((*hmp_chunk[i] & 0x7F) << var_len_shift);
hmp_chunk[i]++;
chunk_length[i]--;
} while (!chunk_delta[i]);

if ((!smallest_delta) || (smallest_delta > chunk_delta[i])) {
Expand Down
55 changes: 37 additions & 18 deletions src/f_midi.c
Expand Up @@ -43,8 +43,8 @@ _WM_ParseNewMidi(uint8_t *midi_data, uint32_t midi_size) {

uint32_t tmp_val;
uint32_t midi_type;
uint32_t track_size;
uint8_t **tracks;
uint32_t *track_size;
uint32_t end_of_tracks = 0;
uint32_t no_tracks;
uint32_t i;
Expand All @@ -56,15 +56,11 @@ _WM_ParseNewMidi(uint8_t *midi_data, uint32_t midi_size) {
float sample_count_f = 0.0;
float sample_remainder = 0.0;
uint8_t *sysex_store = NULL;
// uint32_t sysex_store_len = 0;

uint32_t *track_delta;
uint8_t *track_end;
uint32_t smallest_delta = 0;
uint32_t subtract_delta = 0;
// uint32_t tmp_length = 0;
// uint8_t current_event = 0;
// uint8_t current_event_ch = 0;
uint8_t *running_event;
uint32_t setup_ret = 0;

Expand Down Expand Up @@ -151,6 +147,7 @@ _WM_ParseNewMidi(uint8_t *midi_data, uint32_t midi_size) {
_WM_midi_setup_divisions(mdi,divisions);

tracks = malloc(sizeof(uint8_t *) * no_tracks);
track_size = malloc(sizeof(uint32_t) * no_tracks);
track_delta = malloc(sizeof(uint32_t) * no_tracks);
track_end = malloc(sizeof(uint8_t) * no_tracks);
running_event = malloc(sizeof(uint8_t) * no_tracks);
Expand All @@ -168,38 +165,42 @@ _WM_ParseNewMidi(uint8_t *midi_data, uint32_t midi_size) {
midi_data += 4;
midi_size -= 4;

track_size = *midi_data++ << 24;
track_size |= *midi_data++ << 16;
track_size |= *midi_data++ << 8;
track_size |= *midi_data++;
/* track size */
tmp_val = *midi_data++ << 24;
tmp_val |= *midi_data++ << 16;
tmp_val |= *midi_data++ << 8;
tmp_val |= *midi_data++;
midi_size -= 4;
if (midi_size < track_size) {
if (midi_size < tmp_val) {
_WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT, "(too short)", 0);
goto _end;
}
if (track_size < 3) {
if (tmp_val < 3) {
_WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT, "(bad track size)", 0);
goto _end;
}
if ((midi_data[track_size - 3] != 0xFF)
|| (midi_data[track_size - 2] != 0x2F)
|| (midi_data[track_size - 1] != 0x00)) {
if ((midi_data[tmp_val - 3] != 0xFF)
|| (midi_data[tmp_val - 2] != 0x2F)
|| (midi_data[tmp_val - 1] != 0x00)) {
_WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT, "(missing EOT)", 0);
goto _end;
}
tracks[i] = midi_data;
midi_data += track_size;
midi_size -= track_size;
track_size[i] = tmp_val;
midi_data += tmp_val;
midi_size -= tmp_val;
track_end[i] = 0;
running_event[i] = 0;
track_delta[i] = 0;

while (*tracks[i] > 0x7F) {
track_delta[i] = (track_delta[i] << 7) + (*tracks[i] & 0x7F);
tracks[i]++;
track_size[i]--;
}
track_delta[i] = (track_delta[i] << 7) + (*tracks[i] & 0x7F);
tracks[i]++;
track_size[i]--;

if (midi_type == 1 ) {
if (track_delta[i] < smallest_delta) {
Expand Down Expand Up @@ -243,7 +244,7 @@ _WM_ParseNewMidi(uint8_t *midi_data, uint32_t midi_size) {
}
}
do {
setup_ret = _WM_SetupMidiEvent(mdi, tracks[i], running_event[i]);
setup_ret = _WM_SetupMidiEvent(mdi, tracks[i], track_size[i], running_event[i]);
if (setup_ret == 0) {
goto _end;
}
Expand All @@ -259,6 +260,7 @@ _WM_ParseNewMidi(uint8_t *midi_data, uint32_t midi_size) {
end_of_tracks++;
track_end[i] = 1;
tracks[i] += 3;
track_size[i] -= 3;
goto NEXT_TRACK;
} else if ((tracks[i][0] == 0xff) && (tracks[i][1] == 0x51) && (tracks[i][2] == 0x03)) {
/* Tempo */
Expand All @@ -270,15 +272,23 @@ _WM_ParseNewMidi(uint8_t *midi_data, uint32_t midi_size) {
}
}
tracks[i] += setup_ret;
track_size[i] -= setup_ret;

if (*tracks[i] > 0x7f) {
do {
if (!track_size[i]) break;
track_delta[i] = (track_delta[i] << 7) + (*tracks[i] & 0x7F);
tracks[i]++;
track_size[i]--;
} while (*tracks[i] > 0x7f);
}
if (!track_size[i]) {
_WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT, "(too short)", 0);
goto _end;
}
track_delta[i] = (track_delta[i] << 7) + (*tracks[i] & 0x7F);
tracks[i]++;
track_size[i]--;
} while (!track_delta[i]);
if ((!smallest_delta) || (smallest_delta > track_delta[i])) {
smallest_delta = track_delta[i];
Expand All @@ -304,7 +314,7 @@ _WM_ParseNewMidi(uint8_t *midi_data, uint32_t midi_size) {
for (i = 0; i < no_tracks; i++) {
running_event[i] = 0;
do {
setup_ret = _WM_SetupMidiEvent(mdi, tracks[i], running_event[i]);
setup_ret = _WM_SetupMidiEvent(mdi, tracks[i], track_size[i], running_event[i]);
if (setup_ret == 0) {
goto _end;
}
Expand All @@ -329,16 +339,24 @@ _WM_ParseNewMidi(uint8_t *midi_data, uint32_t midi_size) {
}
}
tracks[i] += setup_ret;
track_size[i] -= setup_ret;

track_delta[i] = 0;
if (*tracks[i] > 0x7f) {
do {
if (!track_size[i]) break;
track_delta[i] = (track_delta[i] << 7) + (*tracks[i] & 0x7F);
tracks[i]++;
track_size[i]--;
} while (*tracks[i] > 0x7f);
}
if (!track_size[i]) {
_WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT, "(too short)", 0);
goto _end;
}
track_delta[i] = (track_delta[i] << 7) + (*tracks[i] & 0x7F);
tracks[i]++;
track_size[i]--;

sample_count_f = (((float) track_delta[i] * samples_per_delta_f)
+ sample_remainder);
Expand Down Expand Up @@ -372,6 +390,7 @@ _end: free(sysex_store);
free(track_delta);
free(running_event);
free(tracks);
free(track_size);
if (mdi->reverb) return (mdi);
_WM_freeMDI(mdi);
return (NULL);
Expand Down
5 changes: 3 additions & 2 deletions src/f_mus.c
Expand Up @@ -61,7 +61,8 @@ _WM_ParseNewMus(uint8_t *mus_data, uint32_t mus_size) {
float tempo_f = 0.0;
uint16_t mus_freq = 0;
float samples_per_tick_f = 0.0;
uint8_t mus_event[] = { 0, 0, 0, 0 };
#define MUS_SZ 4
uint8_t mus_event[MUS_SZ] = { 0, 0, 0, 0 };
uint8_t mus_event_size = 0;
uint8_t mus_prev_vol[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
uint32_t setup_ret = 0;
Expand Down Expand Up @@ -314,7 +315,7 @@ _WM_ParseNewMus(uint8_t *mus_data, uint32_t mus_size) {
break;
}

setup_ret = _WM_SetupMidiEvent(mus_mdi, (uint8_t *)mus_event, 0);
setup_ret = _WM_SetupMidiEvent(mus_mdi, (uint8_t *)mus_event, MUS_SZ, 0);
if (setup_ret == 0) {
goto _mus_end;
}
Expand Down
2 changes: 1 addition & 1 deletion src/f_xmidi.c
Expand Up @@ -267,7 +267,7 @@ struct _mdi *_WM_ParseNewXmi(uint8_t *xmi_data, uint32_t xmi_size) {
setup_ret = 6;
goto _XMI_Next_Event;
}
if ((setup_ret = _WM_SetupMidiEvent(xmi_mdi,xmi_data,0)) == 0) {
if ((setup_ret = _WM_SetupMidiEvent(xmi_mdi,xmi_data, xmi_size, 0)) == 0) {
goto _xmi_end;
}

Expand Down

0 comments on commit ad6d7cf

Please sign in to comment.