CVE-2017-11664 (C, published 2017-08-17T16:29Z)
Description: value: The _WM_SetupMidiEvent function in internal_midi.c:2122 in WildMIDI 0.4.2 can cause a denial of service (invalid memory read and application crash) via a crafted mid file.
Severity: MEDIUM (CVSS v3 base score: 6.5)
Weakness: CWE-125 \u2014 Out-of-bounds Read
The product reads data past the end, or before the beginning, of the intended buffer.
Repository: https://github.com/Mindwerks/wildmidi
Files changed:
include/internal_midi.h
src/f_hmi.c
src/f_hmp.c
src/f_midi.c
src/f_mus.c
src/f_xmidi.c
src/internal_midi.c
Commit message: 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.


Vulnerable code:
extern uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t running_event);
//  uint32_t hmi_duration_secs = 0;
    //FIXME: This needs to be used for sanity check.
    UNUSED(hmi_size);
                    if ((setup_ret = _WM_SetupMidiEvent(hmi_mdi,hmi_data,hmi_running_event[i])) == 0) {
                        if (*hmi_data > 0x7f) {
                if (*hmi_data > 0x7f) {
                    if ((setup_ret = _WM_SetupMidiEvent(hmp_mdi, hmp_chunk[i], 0)) == 0) {
                if (*hmp_chunk[i] < 0x80) {
    uint32_t track_size;
//  uint32_t sysex_store_len = 0;
//  uint32_t tmp_length = 0;
//  uint8_t current_event = 0;
//  uint8_t current_event_ch = 0;
        track_size = *midi_data++ << 24;
        track_size |= *midi_data++ << 16;
        track_size |= *midi_data++ << 8;
        track_size |= *midi_data++;
        if (midi_size < track_size) {
        if (track_size < 3) {
        if ((midi_data[track_size - 3] != 0xFF)
                || (midi_data[track_size - 2] != 0x2F)
                || (midi_data[track_size - 1] != 0x00)) {
        midi_data += track_size;
        midi_size -= track_size;
                    setup_ret = _WM_SetupMidiEvent(mdi, tracks[i], running_event[i]);
                setup_ret = _WM_SetupMidiEvent(mdi, tracks[i], running_event[i]);
    uint8_t mus_event[] = { 0, 0, 0, 0 };
        setup_ret = _WM_SetupMidiEvent(mus_mdi, (uint8_t *)mus_event, 0);
                        if ((setup_ret = _WM_SetupMidiEvent(xmi_mdi,xmi_data,0)) == 0) {
uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t running_event) {
                    if (*event_data > 0x7f) {
                    if (*event_data > 0x7f) {
                    if (*event_data > 0x7f) {
                    if (*event_data > 0x7f) {
                    if (*event_data > 0x7f) {
                    if (*event_data > 0x7f) {
                    if (*event_data > 0x7f) {
                    if (*event_data > 0x7f) {
                if (!sysex_len) break;

Fixed code:
extern uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint32_t siz, uint8_t running_event);
    uint32_t data_siz;
                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];
                        hmi_tmp += 4;
                        hmi_tmp = 8;
                    } else {
                        hmi_tmp = 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;
                    if ((setup_ret = _WM_SetupMidiEvent(hmi_mdi,hmi_data,data_siz,hmi_running_event[i])) == 0) {
                        data_siz -= setup_ret;
                        if (data_siz && *hmi_data > 0x7f) {
                                if (!data_siz) break;
                                data_siz--;
                        if (!data_siz) {
                            _WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_HMI, "file too short", 0);
                            goto _hmi_end;
                        }
                        data_siz--;
                        data_siz -= setup_ret;
                if (data_siz && *hmi_data > 0x7f) {
                        if (!data_siz) break;
                        data_siz--;
                if (!data_siz) {
                    _WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_HMI, "file too short", 0);
                    goto _hmi_end;
                }
                data_siz--;
        chunk_length[i] -= chunk_ofs[i];
                    chunk_length[i] -= 3;
                    if ((setup_ret = _WM_SetupMidiEvent(hmp_mdi, hmp_chunk[i], chunk_length[i], 0)) == 0) {
                        chunk_length[i] -= 3;
                    chunk_length[i] -= setup_ret;
                if (chunk_length[i] && *hmp_chunk[i] < 0x80) {
                        if (! chunk_length[i]) break;
                        chunk_length[i]--;
                if (! chunk_length[i]) {
                    _WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_HMP, "file too short", 0);
                    goto _hmp_end;
                }
                chunk_length[i]--;
    uint32_t *track_size;
    track_size = malloc(sizeof(uint32_t) * no_tracks);
        /* track size */
        tmp_val = *midi_data++ << 24;
        tmp_val |= *midi_data++ << 16;
        tmp_val |= *midi_data++ << 8;
        tmp_val |= *midi_data++;
        if (midi_size < tmp_val) {
        if (tmp_val < 3) {
        if ((midi_data[tmp_val - 3] != 0xFF)
                || (midi_data[tmp_val - 2] != 0x2F)
                || (midi_data[tmp_val - 1] != 0x00)) {
        track_size[i] = tmp_val;
        midi_data += tmp_val;
        midi_size -= tmp_val;
            track_size[i]--;
        track_size[i]--;
                    setup_ret = _WM_SetupMidiEvent(mdi, tracks[i], track_size[i], running_event[i]);
                            track_size[i] -= 3;
                    track_size[i] -= setup_ret;
                            if (!track_size[i]) break;
                            track_size[i]--;
                    if (!track_size[i]) {
                        _WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT, "(too short)", 0);
                        goto _end;
                    }
                    track_size[i]--;
                setup_ret = _WM_SetupMidiEvent(mdi, tracks[i], track_size[i], running_event[i]);
                track_size[i] -= setup_ret;
                        if (!track_size[i]) break;
                        track_size[i]--;
                if (!track_size[i]) {
                    _WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT, "(too short)", 0);
                    goto _end;
                }
                track_size[i]--;
    free(track_size);
#define MUS_SZ 4
    uint8_t mus_event[MUS_SZ] = { 0, 0, 0, 0 };
        setup_ret = _WM_SetupMidiEvent(mus_mdi, (uint8_t *)mus_event, MUS_SZ, 0);
                        if ((setup_ret = _WM_SetupMidiEvent(xmi_mdi,xmi_data, xmi_size, 0)) == 0) {
uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint32_t siz, uint8_t running_event) {
    if (!siz) goto shortbuf;

        if (--siz == 0) goto shortbuf;
            if (siz < 2) goto shortbuf;
            if (siz < 2) goto shortbuf;
            if (siz < 2) goto shortbuf;
            if (siz < 2) goto shortbuf;
            if (siz < 2) goto shortbuf;
                    if (siz < 4) goto shortbuf;
                    if (--siz && *event_data > 0x7f) {
                            if (!siz) break;
                            siz--;
                    if (!siz) goto shortbuf;
                    if (--siz < tmp_length) goto shortbuf;
                    if (!tmp_length) break; /* bad file? */
                    if (--siz && *event_data > 0x7f) {
                            if (!siz) break;
                            siz--;
                    if (!siz) goto shortbuf;
                    if (--siz < tmp_length) goto shortbuf;
                    if (!tmp_length) break; /* bad file? */
                    if (--siz && *event_data > 0x7f) {
                            if (!siz) break;
                            siz--;
                    if (!siz) goto shortbuf;
                    if (--siz < tmp_length) goto shortbuf;
                    if (!tmp_length) break; /* bad file? */
                    if (--siz && *event_data > 0x7f) {
                            if (!siz) break;
                            siz--;
                    if (!siz) goto shortbuf;
                    if (--siz < tmp_length) goto shortbuf;
                    if (!tmp_length) break; /* bad file? */
                    if (--siz && *event_data > 0x7f) {
                            if (!siz) break;
                            siz--;
                    if (!siz) goto shortbuf;
                    if (--siz < tmp_length) goto shortbuf;
                    if (!tmp_length) break; /* bad file? */
                    if (--siz && *event_data > 0x7f) {
                            if (!siz) break;
                            siz--;
                    if (!siz) goto shortbuf;
                    if (--siz < tmp_length) goto shortbuf;
                    if (!tmp_length) break; /* bad file? */
                    if (--siz && *event_data > 0x7f) {
                            if (!siz) break;
                            siz--;
                    if (!siz) goto shortbuf;
                    if (--siz < tmp_length) goto shortbuf;
                    if (!tmp_length) break; /* bad file? */
                    if (siz < 3) goto shortbuf;
                    if (siz < 3) goto shortbuf;
                    if (siz < 2) goto shortbuf;
                    if (siz < 5) goto shortbuf;
                    if (siz < 7) goto shortbuf;
                    if (siz < 6) goto shortbuf;
                    if (siz < 4) goto shortbuf;
                    if (--siz && *event_data > 0x7f) {
                            if (!siz) break;
                            siz--;
                    if (!siz) goto shortbuf;
                    if (--siz < tmp_length) goto shortbuf;
                        if (!siz) break;
                        siz--;
                if (!siz) goto shortbuf;
                if (--siz < sysex_len) goto shortbuf;
                if (!sysex_len) break; /* bad file? */

shortbuf:
    _WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT, "(input too short)", 0);
    return 0;