Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 34 additions & 8 deletions src/smf_load.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ expected_sysex_length(const unsigned char status, const unsigned char *second_by
{
int sysex_length, len;

assert(status == 0xF0);
assert(status == 0xF0 || status == 0xF7);

if (buffer_length < 3) {
g_critical("SMF error: end of buffer in expected_sysex_length().");
Expand Down Expand Up @@ -441,7 +441,7 @@ extract_escaped_event(const unsigned char *buf, const int buffer_length, smf_eve

message_length = expected_escaped_length(status, c, buffer_length - 1, &vlq_length);

if (message_length < 0)
if (message_length <= 0)
return (-3);

c += vlq_length;
Expand All @@ -460,12 +460,12 @@ extract_escaped_event(const unsigned char *buf, const int buffer_length, smf_eve

memcpy(event->midi_buffer, c, message_length);

if (smf_event_is_valid(event)) {
if (!smf_event_is_valid(event)) {
g_critical("Escaped event is invalid.");
return (-1);
}

if (smf_event_is_system_realtime(event) || smf_event_is_system_common(event)) {
if (!(smf_event_is_system_realtime(event) || smf_event_is_system_common(event))) {
g_warning("Escaped event is not System Realtime nor System Common.");
}

Expand Down Expand Up @@ -503,11 +503,21 @@ extract_midi_event(const unsigned char *buf, const int buffer_length, smf_event_
return (-1);
}

if (is_sysex_byte(status))
if (is_sysex_byte(status)) {
if (c == buf) {
g_critical("SMF error: running status is not applicable to System Exclusive events.");
return (-2);
}
return (extract_sysex_event(buf, buffer_length, event, len, last_status));
}

if (is_escape_byte(status))
if (is_escape_byte(status)) {
if (c == buf) {
g_critical("SMF error: running status is not applicable to Escape events.");
return (-2);
}
return (extract_escaped_event(buf, buffer_length, event, len, last_status));
}

/* At this point, "c" points to first byte following the status byte. */
message_length = expected_message_length(status, c, buffer_length - (c - buf));
Expand Down Expand Up @@ -768,12 +778,23 @@ smf_event_is_valid(const smf_event_t *event)
static int
parse_mtrk_chunk(smf_track_t *track)
{
smf_t *smf = track->smf;
smf_event_t *event;

if (parse_mtrk_header(track))
return (-1);

if (track->file_buffer + track->file_buffer_length > smf->file_buffer + smf->file_buffer_length) {
/* Truncated track? */
track->file_buffer_length = smf->file_buffer_length - (track->file_buffer - smf->file_buffer);
}

for (;;) {
if (track->next_event_offset == track->file_buffer_length) {
g_warning("SMF warning: The track did not finish with the End of Track event.");
break;
}

event = parse_next_event(track);

/* Couldn't parse an event? */
Expand Down Expand Up @@ -869,20 +890,25 @@ smf_load_from_memory(const void *buffer, const int buffer_length)
smf->file_buffer_length = buffer_length;
smf->next_chunk_offset = 0;

if (parse_mthd_chunk(smf))
if (parse_mthd_chunk(smf)) {
smf_delete(smf);
return (NULL);
}

for (i = 1; i <= smf->expected_number_of_tracks; i++) {
smf_track_t *track = smf_track_new();
if (track == NULL)
if (track == NULL) {
smf_delete(smf);
return (NULL);
}

smf_add_track(smf, track);

/* Skip unparseable chunks. */
if (parse_mtrk_chunk(track)) {
g_warning("SMF warning: Cannot load track.");
smf_track_delete(track);
break;
}

track->file_buffer = NULL;
Expand Down
5 changes: 5 additions & 0 deletions src/smf_tempo.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ maybe_add_to_tempo_map(smf_event_t *event)

/* Tempo Change? */
if (event->midi_buffer[1] == 0x51) {
if (event->midi_buffer_length < 6) {
g_critical("Tempo Change event seems truncated.");
return;
}

int new_tempo = (event->midi_buffer[3] << 16) + (event->midi_buffer[4] << 8) + event->midi_buffer[5];
if (new_tempo <= 0) {
g_critical("Ignoring invalid tempo change.");
Expand Down