From cffb65f2ff85f19418ed121275901674824e52ca Mon Sep 17 00:00:00 2001 From: "J.W. Jagersma" Date: Mon, 26 Sep 2022 20:35:46 +0200 Subject: [PATCH] djgpp: Set TZ=UTC to convert UTC timestamp to time_t Since djgpp has neither a timezone variable or timegm(), this horrible method must be used. It is the only one I could find that produces accurate results, and is recommended as portable alternative to timegm() by the GNU libc manual. Reference: https://www.gnu.org/software/libc/manual/html_node/Broken_002ddown-Time.html#index-timegm Now, a much nicer alternative solution could be: timestamp_local = mktime(timestamp_tm); timestamp_utc = timestamp_local + timestamp_tm->tm_gmtoff - (timestamp_tm->tm_isdst ? 3600 : 0); This works due to the fact that mktime() populates the tm_gmtoff and tm_isdst fields in the source timestamp. It is accurate everywhere in the world, *except* on Lord Howe Island, Australia, where a 30 minute DST offset is used. Reviewed-by: Richard Levitte Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/19274) --- crypto/asn1/a_time.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/crypto/asn1/a_time.c b/crypto/asn1/a_time.c index 23828b1e314..92be1109a2f 100644 --- a/crypto/asn1/a_time.c +++ b/crypto/asn1/a_time.c @@ -605,7 +605,9 @@ time_t ossl_asn1_string_to_time_t(const char *asn1_string) { ASN1_TIME *timestamp_asn1 = NULL; struct tm *timestamp_tm = NULL; -#ifndef USE_TIMEGM +#if defined(__DJGPP__) + char *tz = NULL; +#elif !defined(USE_TIMEGM) time_t timestamp_local; #endif time_t timestamp_utc; @@ -627,17 +629,38 @@ time_t ossl_asn1_string_to_time_t(const char *asn1_string) ASN1_TIME_free(timestamp_asn1); return -1; } + ASN1_TIME_free(timestamp_asn1); + +#if defined(__DJGPP__) + /* + * This is NOT thread-safe. Do not use this method for platforms other + * than djgpp. + */ + tz = getenv("TZ"); + if (tz != NULL) { + tz = OPENSSL_strdup(tz); + if (tz == NULL) { + OPENSSL_free(timestamp_tm); + return -1; + } + } + setenv("TZ", "UTC", 1); + + timestamp_utc = mktime(timestamp_tm); -#ifdef USE_TIMEGM + if (tz != NULL) { + setenv("TZ", tz, 1); + OPENSSL_free(tz); + } else { + unsetenv("TZ"); + } +#elif defined(USE_TIMEGM) timestamp_utc = timegm(timestamp_tm); - OPENSSL_free(timestamp_tm); #else timestamp_local = mktime(timestamp_tm); - OPENSSL_free(timestamp_tm); - timestamp_utc = timestamp_local - timezone; #endif + OPENSSL_free(timestamp_tm); - ASN1_TIME_free(timestamp_asn1); return timestamp_utc; } -- 2.47.3