Handle time out of range in libx52_set_clock

Prior to this change, the assumption was that localtime/gmtime would
never fail, regardless of the time value provided to it. However,
testing on an Ubuntu 20.04 machine revealed that the representable
range of time_t was about 56 bits, values that exceed a 56 bit
representation would cause localtime/gmtime to return a NULL pointer.

This change replaces the use of localtime/gmtime with their
corresponding thread-safe variants, and checks the return value against
NULL. If it matches a NULL value, then it will return an error and not
update the clocks.
pull/22/head
nirenjan 2020-06-04 15:28:39 -07:00
parent cdc6a594e4
commit b6ebdef7ef
3 changed files with 13 additions and 4 deletions

View File

@ -21,6 +21,7 @@ The format is based upon [Keep a Changelog].
### Fixed
- Error reporting in x52cli and x52test commands.
- Handling of very large time_t values in `libx52_set_clock`
## [0.2.0] - 2020-04-14
### Changed

View File

@ -178,7 +178,7 @@ typedef enum {
/** No change necessary, try again */
LIBX52_ERROR_TRY_AGAIN,
/** Clock timezone out of range */
/** Clock time value or timezone out of range */
LIBX52_ERROR_OUT_OF_RANGE,
/** Error encountered during USB interaction */
@ -454,7 +454,7 @@ int libx52_set_clock(libx52_device *x52, time_t time, int local);
* @param[in] offset Offset in minutes from GMT (east is positive, west
* is negative)
*
* @returns
* @returns
* - 0 on success
* - \ref LIBX52_ERROR_INVALID_PARAM if \p x52 is invalid
* - \ref LIBX52_ERROR_NOT_SUPPORTED if \p clock is \ref LIBX52_CLOCK_1

View File

@ -19,6 +19,7 @@
int libx52_set_clock(libx52_device *x52, time_t time, int local)
{
struct tm timeval;
struct tm *ptr;
int local_tz;
int local_date_day;
int local_date_month;
@ -32,17 +33,24 @@ int libx52_set_clock(libx52_device *x52, time_t time, int local)
}
if (local) {
timeval = *localtime(&time);
ptr = localtime_r(&time, &timeval);
/* timezone from time.h presents the offset in seconds west of GMT.
* Negate and divide by 60 to get the offset in minutes east of GMT.
*/
local_tz = (int)(-timezone / 60);
} else {
timeval = *gmtime(&time);
ptr = gmtime_r(&time, &timeval);
/* No offset from GMT */
local_tz = 0;
}
if (ptr == NULL) {
/* Time conversion failed. This happens if the time value exceeds the
* range which can be represented.
*/
return LIBX52_ERROR_OUT_OF_RANGE;
}
local_date_day = timeval.tm_mday;
local_date_month = timeval.tm_mon + 1;
local_date_year = timeval.tm_year % 100;