diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-10-03 10:29:40 -0400 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2015-10-03 10:41:03 -0400 |
commit | 769365b4db6b1beeeb1e86d106cf2ffead975747 (patch) | |
tree | 534b5bf41212d950a1d7bd1d1c94b6e92ec96e0f | |
parent | 08db242e0e5855a4673e4caf9549bed78012737c (diff) | |
download | subsurface-769365b4db6b1beeeb1e86d106cf2ffead975747.tar.gz |
Clean up Divesoft Freedome time parsing
So Anton Lundin says that the 32-bit timestamp for the Divesoft Freedom
is indeed a signed offset from Jan 1, 2000.
This does that, but also extracts the whole thing into a helper function
and makes sure that there are no overflows at any point by using
"timestamp_t" in the whole series, and all the operations are "obviously
safe" in their types (ie no "unsigned char gets widened to 'int' and
then we shift it left by 24 bits").
Signed-off-by: Linus Torvalds <torvalds@linux-fundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
-rw-r--r-- | parse-xml.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/parse-xml.c b/parse-xml.c index 1aaeb42fe..b2bc76f0c 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -3246,6 +3246,24 @@ int parse_divinglog_buffer(sqlite3 *handle, const char *url, const char *buffer, return 0; } +/* + * Parse a signed 32-bit integer in little-endian mode, + * that is seconds since Jan 1, 2000. + */ +static timestamp_t parse_dlf_timestamp(unsigned char *buffer) +{ + timestamp_t offset; + + offset = (signed char) buffer[3]; + offset = (offset << 8) + buffer[2]; + offset = (offset << 8) + buffer[1]; + offset = (offset << 8) + buffer[0]; + + // Jan 1, 2000 is 946684800 seconds after Jan 1, 1970, which is + // the Unix epoch date that "timestamp_t" uses. + return offset + 946684800; +} + int parse_dlf_buffer(unsigned char *buffer, size_t size) { unsigned char *ptr = buffer; @@ -3268,12 +3286,7 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size) // (ptr[7] << 8) + ptr[6] Is "Serial" snprintf(serial, sizeof(serial), "%d", (ptr[7] << 8) + ptr[6]); cur_dc->serial = strdup(serial); - // Dive start time in seconds since 2000-01-01 00:00 - // let's avoid implicit sign extensions - // ("unsigned char" is expanded to "int" in C arithmetic, so - // (ptr[11] << 24) can be a signed integer) - uint32_t offset = (ptr[11] << 24) + (ptr[10] << 16) + (ptr[9] << 8) + ptr[8]; - cur_dc->when = (timestamp_t) offset + 946684800; + cur_dc->when = parse_dlf_timestamp(ptr + 8); cur_dive->when = cur_dc->when; cur_dc->duration.seconds = ((ptr[14] & 0xFE) << 16) + (ptr[13] << 8) + ptr[12]; |