Diff between 3cc6624dcefa9c3a804ace48694cc52c654efb19 and b53fef50969b49f7c2a1376a11677817d3bdcf80

Changed Files

File Additions Deletions Status
profiles/midi/libmidi.c +31 -7 modified

Full Patch

diff --git a/profiles/midi/libmidi.c b/profiles/midi/libmidi.c
index 4b4df79..7d57e73 100644
--- a/profiles/midi/libmidi.c
+++ b/profiles/midi/libmidi.c
@@ -331,6 +331,30 @@ static size_t handle_end_of_sysex(struct midi_read_parser *parser,
 	return sysex_length + 1; /* +1 because of timestampLow */
 }
 
+/* Searches the end of a SysEx message that contains a timestampLow
+ * before the SysEx end byte. Returns the number of bytes of valid
+ * SysEx payload in the buffer.
+ */
+static size_t sysex_eox_len(const uint8_t *data, size_t size)
+{
+	size_t i = 0;
+
+	MIDI_ASSERT(size > 0);
+
+	if (data[i] == 0xF0)
+		i++;
+
+	/* Search for timestamp low */
+	while (i < size) {
+		if ((data[i] & 0x80)) {
+			i++;
+			break;
+		}
+		i++;
+	}
+
+	return (i < size && data[i] == 0xF7) ? i : 0;
+}
 
 
 size_t midi_read_raw(struct midi_read_parser *parser, const uint8_t *data,
@@ -368,14 +392,14 @@ size_t midi_read_raw(struct midi_read_parser *parser, const uint8_t *data,
 
 		/* System Common Messages */
 	case 0xF0: /* SysEx Start */ {
-		uint8_t *pos;
+		size_t sysex_length;
 
 		/* cleanup Running Status Message */
 		parser->rstatus = 0;
 
-		/* Avoid parsing if SysEx is contained in one BLE packet */
-		if ((pos = memchr(data + i, 0xF7, size - i))) {
-			const size_t sysex_length = pos - (data + i);
+		sysex_length = sysex_eox_len(data + i, size - i);
+		/* Search for End of SysEx message in one BLE message */
+		if (sysex_length > 0) {
 			midi_size = handle_end_of_sysex(parser, ev, data + i,
 			                                sysex_length);
 		} else {
@@ -424,10 +448,10 @@ size_t midi_read_raw(struct midi_read_parser *parser, const uint8_t *data,
 
 		/* Check for SysEx messages */
 		if (parser->sysex_stream.len > 0) {
-			uint8_t *pos;
+			size_t sysex_length;
 
-			if ((pos = memchr(data + i, 0xF7, size - i))) {
-				const size_t sysex_length = pos - (data + i);
+			sysex_length = sysex_eox_len(data + i, size - i);
+			if (sysex_length > 0) {
 				midi_size = handle_end_of_sysex(parser, ev, data + i,
 				                                sysex_length);
 			} else {