From 3dbfe9d66d10085a2859960cb82e0a18f9271072 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 29 Dec 2016 19:16:15 +0100 Subject: [PATCH] Detect overwritten dive profiles The logbook entries are stored separately from the profile data. If the profile ringbuffer is filled faster than the logbook ringbuffer, then the oldest logbook entries can still point to profile data that has already been overwritten with newer data. To detect such overwritten profile data, we keep track of the remaining space in the profile ringbuffer. --- src/cressi_leonardo.c | 50 +++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/src/cressi_leonardo.c b/src/cressi_leonardo.c index cda8a0c..7e1df90 100644 --- a/src/cressi_leonardo.c +++ b/src/cressi_leonardo.c @@ -480,6 +480,8 @@ cressi_leonardo_extract_dives (dc_device_t *abstract, const unsigned char data[] return DC_STATUS_NOMEMORY; } + unsigned int previous = 0; + unsigned int remaining = RB_PROFILE_END - RB_PROFILE_BEGIN; for (unsigned int i = 0; i < count; ++i) { unsigned int idx = (latest + RB_LOGBOOK_COUNT - i) % RB_LOGBOOK_COUNT; unsigned int offset = RB_LOGBOOK_BEGIN + idx * RB_LOGBOOK_SIZE; @@ -495,19 +497,12 @@ cressi_leonardo_extract_dives (dc_device_t *abstract, const unsigned char data[] return DC_STATUS_DATAFORMAT; } - // Get the same pointers from the profile. - unsigned int header2 = array_uint16_le (data + footer); - unsigned int footer2 = array_uint16_le (data + header); - if (header2 != header || footer2 != footer) { - ERROR (context, "Invalid ringbuffer pointer detected (0x%04x 0x%04x).", header2, footer2); + if (previous && previous != footer + 2) { + ERROR (abstract->context, "Profiles are not continuous (0x%04x 0x%04x 0x%04x).", header, footer, previous); free (buffer); return DC_STATUS_DATAFORMAT; } - // Calculate the profile address and length. - unsigned int address = header + 2; - unsigned int length = RB_PROFILE_DISTANCE (header, footer) - 2; - // Check the fingerprint data. if (device && memcmp (data + offset + 8, device->fingerprint, sizeof (device->fingerprint)) == 0) break; @@ -515,19 +510,42 @@ cressi_leonardo_extract_dives (dc_device_t *abstract, const unsigned char data[] // Copy the logbook entry. memcpy (buffer, data + offset, RB_LOGBOOK_SIZE); - // Copy the profile data. - if (address + length > RB_PROFILE_END) { - unsigned int len_a = RB_PROFILE_END - address; - unsigned int len_b = length - len_a; - memcpy (buffer + RB_LOGBOOK_SIZE, data + address, len_a); - memcpy (buffer + RB_LOGBOOK_SIZE + len_a, data + RB_PROFILE_BEGIN, len_b); + // Calculate the profile address and length. + unsigned int address = header + 2; + unsigned int length = RB_PROFILE_DISTANCE (header, footer) - 2; + + if (remaining && remaining >= length + 4) { + // Get the same pointers from the profile. + unsigned int header2 = array_uint16_le (data + footer); + unsigned int footer2 = array_uint16_le (data + header); + if (header2 != header || footer2 != footer) { + ERROR (context, "Invalid ringbuffer pointer detected (0x%04x 0x%04x).", header2, footer2); + free (buffer); + return DC_STATUS_DATAFORMAT; + } + + // Copy the profile data. + if (address + length > RB_PROFILE_END) { + unsigned int len_a = RB_PROFILE_END - address; + unsigned int len_b = length - len_a; + memcpy (buffer + RB_LOGBOOK_SIZE, data + address, len_a); + memcpy (buffer + RB_LOGBOOK_SIZE + len_a, data + RB_PROFILE_BEGIN, len_b); + } else { + memcpy (buffer + RB_LOGBOOK_SIZE, data + address, length); + } + + remaining -= length + 4; } else { - memcpy (buffer + RB_LOGBOOK_SIZE, data + address, length); + // No more profile data available! + remaining = 0; + length = 0; } if (callback && !callback (buffer, RB_LOGBOOK_SIZE + length, buffer + 8, sizeof (device->fingerprint), userdata)) { break; } + + previous = header; } free (buffer);