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.
This commit is contained in:
Jef Driesen 2016-12-29 19:16:15 +01:00
parent 8c71aebe45
commit 3dbfe9d66d

View File

@ -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);