From 24f800d1852449734e10d65f5ec218199b076db3 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Fri, 26 Oct 2018 16:07:38 +0200 Subject: [PATCH] Add a workaround for invalid ringbuffer begin pointers Unfortunately there are several devices with an invalid ringbuffer begin pointer. In such cases, the strict validation of the pointer causes the download to fail, without being able to download any dives at all. Since the begin pointer is only needed to detect the start of the oldest dive, we can fall back to downloading the entire profile ringbuffer. Usually we can still detect the start of the oldest dive in some other (indirect) way. For example when reaching past the end of the ringbuffer, or the presence of invalid pointers in the linked list structure. The result is that, we'll be able to download at least some dives before hitting some other error. --- src/suunto_common2.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/suunto_common2.c b/src/suunto_common2.c index 4aa1699..fd56562 100644 --- a/src/suunto_common2.c +++ b/src/suunto_common2.c @@ -287,16 +287,22 @@ suunto_common2_device_foreach (dc_device_t *abstract, dc_dive_callback_t callbac if (last < layout->rb_profile_begin || last >= layout->rb_profile_end || end < layout->rb_profile_begin || - end >= layout->rb_profile_end || - begin < layout->rb_profile_begin || - begin >= layout->rb_profile_end) + end >= layout->rb_profile_end) { ERROR (abstract->context, "Invalid ringbuffer pointer detected (0x%04x 0x%04x 0x%04x %u).", begin, last, end, count); return DC_STATUS_DATAFORMAT; } // Calculate the total amount of bytes. - unsigned int remaining = RB_PROFILE_DISTANCE (layout, begin, end, count != 0); + unsigned int remaining = 0; + if (begin < layout->rb_profile_begin || begin >= layout->rb_profile_end) { + // Fall back to downloading the entire ringbuffer as workaround + // for an invalid begin pointer! + ERROR (abstract->context, "Invalid ringbuffer pointer detected (0x%04x 0x%04x 0x%04x %u).", begin, last, end, count); + remaining = layout->rb_profile_end - layout->rb_profile_begin; + } else { + remaining = RB_PROFILE_DISTANCE (layout, begin, end, count != 0); + } // Update and emit a progress event. progress.maximum -= (layout->rb_profile_end - layout->rb_profile_begin) - remaining;