CVE-2017-11664 (published 2017-08-17T16:29Z)

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 v2 base score: 4.3 (AV:N/AC:M/Au:N/C:N/I:N/A:P)
CVSS v3 base score: 6.5, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: CWE-125
cwe_name: Out-of-bounds Read
description: The product reads data past the end, or before the beginning, of the intended buffer.
extended_description: 
            
            
             
			 
         
         

Fix information:
repo_url: https://github.com/Mindwerks/wildmidi
commit_details: repo_url: https://github.com/Mindwerks/wildmidi
author: sezero
author_date: 2017-08-02 17:55:10+03:00
msg: 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.
repository: repo_url: https://github.com/Mindwerks/wildmidi
repo_name: Mindwerks/wildmidi
description: WildMIDI is a simple software midi player which has a core softsynth library that can be used with other applications.
repo_language: C
owner: Mindwerks
file_changes: filename: internal_midi.h
change_type: ModificationType.MODIFY
diff: @@ -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);

programming_language: C
filename: f_hmi.c
change_type: ModificationType.MODIFY
diff: @@ -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;
@@ -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);
@@ -216,6 +214,11 @@ _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.
@@ -223,14 +226,23 @@ _WM_ParseNewHmi(uint8_t *hmi_data, uint32_t hmi_size) {
                         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)) {
@@ -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) {
@@ -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])) {

programming_language: C
filename: f_hmp.c
change_type: ModificationType.MODIFY
diff: @@ -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;
     }
@@ -273,10 +274,11 @@ _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;
                     }
 
@@ -284,6 +286,7 @@ _WM_ParseNewHmp(uint8_t *hmp_data, uint32_t hmp_size) {
                         /* 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)) {
@@ -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])) {

programming_language: C
filename: f_midi.c
change_type: ModificationType.MODIFY
diff: @@ -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;
@@ -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;
 
@@ -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);
@@ -168,28 +165,30 @@ _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;
@@ -197,9 +196,11 @@ _WM_ParseNewMidi(uint8_t *midi_data, uint32_t midi_size) {
         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) {
@@ -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;
                     }
@@ -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 */
@@ -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];
@@ -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;
                 }
@@ -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);
@@ -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);

programming_language: C
filename: f_mus.c
change_type: ModificationType.MODIFY
diff: @@ -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;
@@ -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;
         }

programming_language: Rust
filename: f_xmidi.c
change_type: ModificationType.MODIFY
diff: @@ -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;
                         }
 

programming_language: C
filename: internal_midi.c
change_type: ModificationType.MODIFY
diff: @@ -1962,7 +1962,7 @@ void _WM_freeMDI(struct _mdi *mdi) {
     free(mdi);
 }
 
-uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t running_event) {
+uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint32_t siz, uint8_t running_event) {
     /*
      Only add standard MIDI and Sysex events in here.
      Non-standard events need to be handled by calling function
@@ -1978,10 +1978,13 @@ uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t runn
     uint8_t data_2 = 0;
     char *text = NULL;
 
+    if (!siz) goto shortbuf;
+
     if (event_data[0] >= 0x80) {
         command = *event_data & 0xf0;
         channel = *event_data++ & 0x0f;
         ret_cnt++;
+        if (--siz == 0) goto shortbuf;
     } else {
         command = running_event & 0xf0;
         channel = running_event & 0x0f;
@@ -1990,6 +1993,7 @@ uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t runn
     switch(command) {
         case 0x80:
         _SETUP_NOTEOFF:
+            if (siz < 2) goto shortbuf;
             data_1 = *event_data++;
             data_2 = *event_data++;
             _WM_midi_setup_noteoff(mdi, channel, data_1, data_2);
@@ -1997,18 +2001,21 @@ uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t runn
             break;
         case 0x90:
             if (event_data[1] == 0) goto _SETUP_NOTEOFF; /* A velocity of 0 in a note on is actually a note off */
+            if (siz < 2) goto shortbuf;
             data_1 = *event_data++;
             data_2 = *event_data++;
             midi_setup_noteon(mdi, channel, data_1, data_2);
             ret_cnt += 2;
             break;
         case 0xa0:
+            if (siz < 2) goto shortbuf;
             data_1 = *event_data++;
             data_2 = *event_data++;
             midi_setup_aftertouch(mdi, channel, data_1, data_2);
             ret_cnt += 2;
             break;
         case 0xb0:
+            if (siz < 2) goto shortbuf;
             data_1 = *event_data++;
             data_2 = *event_data++;
             midi_setup_control(mdi, channel, data_1, data_2);
@@ -2025,6 +2032,7 @@ uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t runn
             ret_cnt++;
             break;
         case 0xe0:
+            if (siz < 2) goto shortbuf;
             data_1 = *event_data++;
             data_2 = *event_data++;
             midi_setup_pitch(mdi, channel, ((data_2 << 7) | (data_1 & 0x7f)));
@@ -2041,6 +2049,7 @@ uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t runn
                      Sequence Number
                      We only setting this up here for WM_Event2Midi function
                      */
+                    if (siz < 4) goto shortbuf;
                     midi_setup_sequenceno(mdi, ((event_data[2] << 8) + event_data[3]));
                     ret_cnt += 4;
                 } else if (event_data[0] == 0x01) {
@@ -2048,16 +2057,21 @@ uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t runn
                     /* Get Length */
                     event_data++;
                     ret_cnt++;
-                    if (*event_data > 0x7f) {
+                    if (--siz && *event_data > 0x7f) {
                         do {
+                            if (!siz) break;
                             tmp_length = (tmp_length << 7) + (*event_data & 0x7f);
                             event_data++;
+                            siz--;
                             ret_cnt++;
                         } while (*event_data > 0x7f);
                     }
+                    if (!siz) goto shortbuf;
                     tmp_length = (tmp_length << 7) + (*event_data & 0x7f);
                     event_data++;
                     ret_cnt++;
+                    if (--siz < tmp_length) goto shortbuf;
+                    if (!tmp_length) break; /* bad file? */
 
                     text = malloc(tmp_length + 1);
                     memcpy(text, event_data, tmp_length);
@@ -2071,16 +2085,21 @@ uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t runn
                     /* Get Length */
                     event_data++;
                     ret_cnt++;
-                    if (*event_data > 0x7f) {
+                    if (--siz && *event_data > 0x7f) {
                         do {
+                            if (!siz) break;
                             tmp_length = (tmp_length << 7) + (*event_data & 0x7f);
                             event_data++;
+                            siz--;
                             ret_cnt++;
                         } while (*event_data > 0x7f);
                     }
+                    if (!siz) goto shortbuf;
                     tmp_length = (tmp_length << 7) + (*event_data & 0x7f);
                     event_data++;
                     ret_cnt++;
+                    if (--siz < tmp_length) goto shortbuf;
+                    if (!tmp_length) break; /* bad file? */
 
                     /* Copy copyright info in the getinfo struct */
                     if (mdi->extra_info.copyright) {
@@ -2107,16 +2126,21 @@ uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t runn
                     /* Get Length */
                     event_data++;
                     ret_cnt++;
-                    if (*event_data > 0x7f) {
+                    if (--siz && *event_data > 0x7f) {
                         do {
+                            if (!siz) break;
                             tmp_length = (tmp_length << 7) + (*event_data & 0x7f);
                             event_data++;
+                            siz--;
                             ret_cnt++;
                         } while (*event_data > 0x7f);
                     }
+                    if (!siz) goto shortbuf;
                     tmp_length = (tmp_length << 7) + (*event_data & 0x7f);
                     event_data++;
                     ret_cnt++;
+                    if (--siz < tmp_length) goto shortbuf;
+                    if (!tmp_length) break; /* bad file? */
 
                     text = malloc(tmp_length + 1);
                     memcpy(text, event_data, tmp_length);
@@ -2130,16 +2154,21 @@ uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t runn
                     /* Get Length */
                     event_data++;
                     ret_cnt++;
-                    if (*event_data > 0x7f) {
+                    if (--siz && *event_data > 0x7f) {
                         do {
+                            if (!siz) break;
                             tmp_length = (tmp_length << 7) + (*event_data & 0x7f);
                             event_data++;
+                            siz--;
                             ret_cnt++;
                         } while (*event_data > 0x7f);
                     }
+                    if (!siz) goto shortbuf;
                     tmp_length = (tmp_length << 7) + (*event_data & 0x7f);
                     event_data++;
                     ret_cnt++;
+                    if (--siz < tmp_length) goto shortbuf;
+                    if (!tmp_length) break; /* bad file? */
 
                     text = malloc(tmp_length + 1);
                     memcpy(text, event_data, tmp_length);
@@ -2153,16 +2182,21 @@ uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t runn
                     /* Get Length */
                     event_data++;
                     ret_cnt++;
-                    if (*event_data > 0x7f) {
+                    if (--siz && *event_data > 0x7f) {
                         do {
+                            if (!siz) break;
                             tmp_length = (tmp_length << 7) + (*event_data & 0x7f);
                             event_data++;
+                            siz--;
                             ret_cnt++;
                         } while (*event_data > 0x7f);
                     }
+                    if (!siz) goto shortbuf;
                     tmp_length = (tmp_length << 7) + (*event_data & 0x7f);
                     event_data++;
                     ret_cnt++;
+                    if (--siz < tmp_length) goto shortbuf;
+                    if (!tmp_length) break; /* bad file? */
 
                     text = malloc(tmp_length + 1);
                     memcpy(text, event_data, tmp_length);
@@ -2176,16 +2210,21 @@ uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t runn
                     /* Get Length */
                     event_data++;
                     ret_cnt++;
-                    if (*event_data > 0x7f) {
+                    if (--siz && *event_data > 0x7f) {
                         do {
+                            if (!siz) break;
                             tmp_length = (tmp_length << 7) + (*event_data & 0x7f);
                             event_data++;
+                            siz--;
                             ret_cnt++;
                         } while (*event_data > 0x7f);
                     }
+                    if (!siz) goto shortbuf;
                     tmp_length = (tmp_length << 7) + (*event_data & 0x7f);
                     event_data++;
                     ret_cnt++;
+                    if (--siz < tmp_length) goto shortbuf;
+                    if (!tmp_length) break; /* bad file? */
 
                     text = malloc(tmp_length + 1);
                     memcpy(text, event_data, tmp_length);
@@ -2199,16 +2238,21 @@ uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t runn
                     /* Get Length */
                     event_data++;
                     ret_cnt++;
-                    if (*event_data > 0x7f) {
+                    if (--siz && *event_data > 0x7f) {
                         do {
+                            if (!siz) break;
                             tmp_length = (tmp_length << 7) + (*event_data & 0x7f);
                             event_data++;
+                            siz--;
                             ret_cnt++;
                         } while (*event_data > 0x7f);
                     }
+                    if (!siz) goto shortbuf;
                     tmp_length = (tmp_length << 7) + (*event_data & 0x7f);
                     event_data++;
                     ret_cnt++;
+                    if (--siz < tmp_length) goto shortbuf;
+                    if (!tmp_length) break; /* bad file? */
 
                     text = malloc(tmp_length + 1);
                     memcpy(text, event_data, tmp_length);
@@ -2222,6 +2266,7 @@ uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t runn
                      Channel Prefix
                      We only setting this up here for WM_Event2Midi function
                      */
+                    if (siz < 3) goto shortbuf;
                     midi_setup_channelprefix(mdi, event_data[2]);
                     ret_cnt += 3;
                 } else if ((event_data[0] == 0x21) && (event_data[1] == 0x01)) {
@@ -2229,6 +2274,7 @@ uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t runn
                      Port Prefix
                      We only setting this up here for WM_Event2Midi function
                      */
+                    if (siz < 3) goto shortbuf;
                     midi_setup_portprefix(mdi, event_data[2]);
                     ret_cnt += 3;
                 } else if ((event_data[0] == 0x2F) && (event_data[1] == 0x00)) {
@@ -2237,6 +2283,7 @@ uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t runn
                      Deal with this inside calling function
                      We only setting this up here for _WM_Event2Midi function
                      */
+                    if (siz < 2) goto shortbuf;
                     _WM_midi_setup_endoftrack(mdi);
                     ret_cnt += 2;
                 } else if ((event_data[0] == 0x51) && (event_data[1] == 0x03)) {
@@ -2245,9 +2292,11 @@ uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t runn
                      Deal with this inside calling function.
                      We only setting this up here for _WM_Event2Midi function
                      */
+                    if (siz < 5) goto shortbuf;
                     _WM_midi_setup_tempo(mdi, ((event_data[2] << 16) + (event_data[3] << 8) + event_data[4]));
                     ret_cnt += 5;
                 } else if ((event_data[0] == 0x54) && (event_data[1] == 0x05)) {
+                    if (siz < 7) goto shortbuf;
                     /*
                      SMPTE Offset
                      We only setting this up here for WM_Event2Midi function
@@ -2265,6 +2314,7 @@ uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t runn
                      Time Signature
                      We only setting this up here for WM_Event2Midi function
                      */
+                    if (siz < 6) goto shortbuf;
                     midi_setup_timesignature(mdi, ((event_data[2] << 24) + (event_data[3] << 16) + (event_data[4] << 8) + event_data[5]));
                     ret_cnt += 6;
                 } else if ((event_data[0] == 0x59) && (event_data[1] == 0x02)) {
@@ -2272,6 +2322,7 @@ uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t runn
                      Key Signature
                      We only setting this up here for WM_Event2Midi function
                      */
+                    if (siz < 4) goto shortbuf;
                     midi_setup_keysignature(mdi, ((event_data[2] << 8) + event_data[3]));
                     ret_cnt += 4;
                 } else {
@@ -2280,16 +2331,20 @@ uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t runn
                      */
                     event_data++;
                     ret_cnt++;
-                    if (*event_data > 0x7f) {
+                    if (--siz && *event_data > 0x7f) {
                         do {
+                            if (!siz) break;
                             tmp_length = (tmp_length << 7) + (*event_data & 0x7f);
                             event_data++;
+                            siz--;
                             ret_cnt++;
                         } while (*event_data > 0x7f);
                     }
+                    if (!siz) goto shortbuf;
                     tmp_length = (tmp_length << 7) + (*event_data & 0x7f);
                     ret_cnt++;
                     ret_cnt += tmp_length;
+                    if (--siz < tmp_length) goto shortbuf;
                 }
 
             } else if ((channel == 0) || (channel == 7)) {
@@ -2301,15 +2356,19 @@ uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t runn
 
                 if (*event_data > 0x7f) {
                     do {
+                        if (!siz) break;
                         sysex_len = (sysex_len << 7) + (*event_data & 0x7F);
                         event_data++;
+                        siz--;
                         ret_cnt++;
                     } while (*event_data > 0x7f);
                 }
+                if (!siz) goto shortbuf;
                 sysex_len = (sysex_len << 7) + (*event_data & 0x7F);
                 event_data++;
-                if (!sysex_len) break;
                 ret_cnt++;
+                if (--siz < sysex_len) goto shortbuf;
+                if (!sysex_len) break; /* bad file? */
 
                 sysex_store = malloc(sizeof(uint8_t) * sysex_len);
                 memcpy(sysex_store, event_data, sysex_len);
@@ -2381,5 +2440,9 @@ uint32_t _WM_SetupMidiEvent(struct _mdi *mdi, uint8_t * event_data, uint8_t runn
     if (ret_cnt == 0)
         _WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT, "(missing event)", 0);
     return ret_cnt;
+
+shortbuf:
+    _WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT, "(input too short)", 0);
+    return 0;
 }
 

programming_language: C