diff --git a/src/hw_ostc3.c b/src/hw_ostc3.c index 6f0354f..e240342 100644 --- a/src/hw_ostc3.c +++ b/src/hw_ostc3.c @@ -727,6 +727,11 @@ hw_ostc3_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, voi if (firmware < 93) length -= 3; } + if (length < RB_LOGBOOK_SIZE_FULL) { + ERROR (abstract->context, "Invalid profile length (%u bytes).", length); + free (header); + return DC_STATUS_DATAFORMAT; + } // Check the fingerprint data. if (memcmp (header + offset + logbook->fingerprint, device->fingerprint, sizeof (device->fingerprint)) == 0) @@ -789,6 +794,26 @@ hw_ostc3_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, voi return rc; } + // Detect invalid profile data. + unsigned int delta = device->hardware == OSTC4 ? 3 : 0; + if (length < RB_LOGBOOK_SIZE_FULL + 2 || + profile[length - 2] != 0xFD || profile[length - 1] != 0xFD) { + // A valid profile should have at least a correct 2 byte + // end-of-profile marker. + WARNING (abstract->context, "Invalid profile end marker detected!"); + length = RB_LOGBOOK_SIZE_FULL; + } else if (length == RB_LOGBOOK_SIZE_FULL + 2) { + // A profile containing only the 2 byte end-of-profile + // marker is considered a valid empty profile. + } else if (length < RB_LOGBOOK_SIZE_FULL + 5 + 2 || + array_uint24_le (profile + RB_LOGBOOK_SIZE_FULL) + delta != array_uint24_le (profile + 9)) { + // If there is more data available, then there should be a + // valid profile header containing a length matching the + // length in the dive header. + WARNING (abstract->context, "Invalid profile header detected."); + length = RB_LOGBOOK_SIZE_FULL; + } + if (callback && !callback (profile, length, profile + 12, sizeof (device->fingerprint), userdata)) break; } diff --git a/src/hw_ostc_parser.c b/src/hw_ostc_parser.c index a96456c..04b9d6f 100644 --- a/src/hw_ostc_parser.c +++ b/src/hw_ostc_parser.c @@ -569,6 +569,13 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call unsigned int header = parser->header; const hw_ostc_layout_t *layout = parser->layout; + // Exit if no profile data available. + if (size == header || (size == header + 2 && + data[header] == 0xFD && data[header + 1] == 0xFD)) { + parser->cached = PROFILE; + return DC_STATUS_SUCCESS; + } + // Check the header length. if (version == 0x23 || version == 0x24) { if (size < header + 5) {