if (smf->next_chunk_offset > smf->file_buffer_length) {
g_critical("SMF error: malformed chunk; truncated file?");
- return (NULL);
}
return (chunk);
uint32_t sysex_length = 0;
uint32_t len = 0;
+#ifndef NDEBUG
+ (void) status;
+#else
assert(status == 0xF0);
+#endif
if (buffer_length < 3) {
g_critical("SMF error: end of buffer in expected_sysex_length().");
status = *buf;
- assert(is_sysex_byte(status));
+ if (!(is_sysex_byte(status))) {
+ g_critical("Corrupt sysex status byte in extract_sysex_event().");
+ return (-6);
+ }
c++;
status = *buf;
- assert(is_escape_byte(status));
+ if (!(is_escape_byte(status))) {
+ g_critical("Corrupt escape status byte in extract_escaped_event().");
+ return (-6);
+ }
c++;
static smf_event_t *
parse_next_event(smf_track_t *track)
{
- uint32_t time = 0;
+ uint32_t etime = 0;
uint32_t len;
size_t buffer_length;
unsigned char *c, *start;
assert(track->next_event_offset > 0);
buffer_length = track->file_buffer_length - track->next_event_offset;
- assert(buffer_length > 0);
-
+ /* if there was no meta-EOT event, buffer_length can be zero. This is
+ an error in the SMF file, but it shouldn't be treated as fatal.
+ */
+ if (buffer_length == 0) {
+ g_warning ("SMF warning: expected EOT at end of track, but none found");
+ goto error;
+ }
/* First, extract time offset from previous event. */
- if (smf_extract_vlq(c, buffer_length, &time, &len))
+ if (smf_extract_vlq(c, buffer_length, &etime, &len)) {
goto error;
+ }
c += len;
buffer_length -= len;
goto error;
/* Now, extract the actual event. */
- if (extract_midi_event(c, buffer_length, event, &len, track->last_status))
+ if (extract_midi_event(c, buffer_length, event, &len, track->last_status)) {
goto error;
+ }
c += len;
buffer_length -= len;
track->last_status = event->midi_buffer[0];
track->next_event_offset += c - start;
- smf_track_add_event_delta_pulses(track, event, time);
+ smf_track_add_event_delta_pulses(track, event, etime);
return (event);
if (event->midi_buffer_length < 4)
return (0);
- if (event->midi_buffer[3] < 1 && event->midi_buffer[3] > 9)
+ if (event->midi_buffer[3] < 1 || event->midi_buffer[3] > 9)
return (0);
return (1);
parse_mtrk_chunk(smf_track_t *track)
{
smf_event_t *event;
+ int ret = 0;
if (parse_mtrk_header(track))
return (-1);
event = parse_next_event(track);
/* Couldn't parse an event? */
- if (event == NULL)
- return (-1);
-
- assert(smf_event_is_valid(event));
+ if (event == NULL || !smf_event_is_valid(event)) {
+ ret = -1;
+ break;
+ }
if (event_is_end_of_track(event))
break;
track->file_buffer_length = 0;
track->next_event_offset = -1;
- return (0);
+ return (ret);
}
/**
smf_load_from_memory(const void *buffer, const size_t buffer_length)
{
int i;
+ int ret;
smf_t *smf = smf_new();
smf_add_track(smf, track);
- /* Skip unparseable chunks. */
- if (parse_mtrk_chunk(track)) {
- g_warning("SMF warning: Cannot load track.");
- smf_track_delete(track);
- continue;
- }
+ ret = parse_mtrk_chunk(track);
track->file_buffer = NULL;
track->file_buffer_length = 0;
track->next_event_offset = -1;
+
+ if (ret) {
+ g_warning("SMF warning: Error parsing track, continuing with data loaded so far.");
+ break;
+ }
}
if (smf->expected_number_of_tracks != smf->number_of_tracks) {