]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Adapt the tests to not care about failures from platform gmtime()
authorBob Beck <beck@openssl.org>
Sat, 4 Oct 2025 13:34:11 +0000 (07:34 -0600)
committerNeil Horman <nhorman@openssl.org>
Tue, 21 Oct 2025 16:19:00 +0000 (12:19 -0400)
Now that we don't use gmtime, timegm and friends from the platform
we should be able to handle all values the same on any platform
with no concerns other than what the platform has decided to use
for time_t.

The hpux #ifdef is removed, as looking at f5e3115361f shows this
was added due to a gmtime() failure on the platform.

This then clears out all the platform specific chaos in helper.c
as an example of why the public API being added is actually
generally useful, as it has been noticed that users of OpenSSL
frequently end up dealing with the same issues in the same really
awful ways in their own software as were were doing in that file
in the tests.

Reviewed-by: Neil Horman <nhorman@openssl.org>
Reviewed-by: Saša Nedvědický <sashan@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/28748)

test/asn1_time_test.c
test/ca_internals_test.c
test/testutil.h
test/testutil/helper.c

index f39f690231b12a7d00514eb1c3dae036307dd49b..2c2ef4ffd51d9c738cde6272aa1d8e3b574547f7 100644 (file)
@@ -482,9 +482,18 @@ static int test_time_dup(void)
 
 static int convert_asn1_to_time_t(int idx)
 {
-    time_t testdateutc;
-
-    testdateutc = test_asn1_string_to_time_t(asn1_to_utc[idx].input);
+    time_t testdateutc = -1;
+
+    if (!test_asn1_string_to_time_t(asn1_to_utc[idx].input, &testdateutc)) {
+        if (!TEST_time_t_eq(-1, asn1_to_utc[idx].expected)) {
+            TEST_info("test_asn1_string_to_time_t (%s) failed: expected %lli"
+                      ", got %lli\n",
+                      asn1_to_utc[idx].input,
+                      (long long int)asn1_to_utc[idx].expected,
+                      (long long int)testdateutc);
+            return 0;
+        }
+    }
 
     if (!TEST_time_t_eq(testdateutc, asn1_to_utc[idx].expected)) {
         TEST_info("test_asn1_string_to_time_t (%s) failed: expected %lli, got %lli\n",
@@ -523,35 +532,35 @@ static int convert_tm_to_asn1_time(void)
 int setup_tests(void)
 {
     /*
-     * On platforms where |time_t| is an unsigned integer, t will be a
-     * positive number.
+     * Unsigned time_t was a very foolish visit from the bad idea bears to
+     * defer one problem for a short period of time by creating an entirely
+     * new class of problems. Nevertheless it exists on some older and
+     * embedded platforms and we have to cope with it.
+     *
+     * On platforms where |time_t| is unsigned, t will be a positive
+     * number.
      *
      * We check if we're on a platform with a signed |time_t| with '!(t > 0)'
      * because some compilers are picky if you do 't < 0', or even 't <= 0'
      * if |t| is unsigned.
+     *
+     * Because we pass values through as time_t in the table test, we must
+     * exclude the negative values if time_t is unsigned.
      */
     time_t t = -1;
-    /*
-     * On some platforms, |time_t| is signed, but a negative value is an
-     * error, and using it with gmtime() or localtime() generates a NULL.
-     * If that is the case, we can't perform tests on negative values.
-     */
-    struct tm *ptm = localtime(&t);
 
     ADD_ALL_TESTS(test_table_pos, OSSL_NELEM(tbl_testdata_pos));
-    if (!(t > 0) && ptm != NULL) {
+    if (!(t > 0)) {
         TEST_info("Adding negative-sign time_t tests");
         ADD_ALL_TESTS(test_table_neg, OSSL_NELEM(tbl_testdata_neg));
     }
     if (sizeof(time_t) > sizeof(uint32_t)) {
         TEST_info("Adding 64-bit time_t tests");
         ADD_ALL_TESTS(test_table_pos_64bit, OSSL_NELEM(tbl_testdata_pos_64bit));
-#ifndef __hpux
-        if (!(t > 0) && ptm != NULL) {
+        if (!(t > 0)) {
             TEST_info("Adding negative-sign 64-bit time_t tests");
             ADD_ALL_TESTS(test_table_neg_64bit, OSSL_NELEM(tbl_testdata_neg_64bit));
         }
-#endif
     }
     ADD_ALL_TESTS(test_table_compare, OSSL_NELEM(tbl_compare_testdata));
     ADD_TEST(test_time_dup);
index 10c3cd90ae69991ac4313ba699d7cb73ce9919df..fe8ccc638fb3f8f832f1a23a9eadfdbbb540dc4f 100644 (file)
@@ -47,7 +47,8 @@ static int test_do_updatedb(void)
     }
 
     testdate = test_get_argument(2);
-    testdateutc = test_asn1_string_to_time_t(testdate);
+    if (!test_asn1_string_to_time_t(testdate, &testdateutc))
+        return 0;
     if (TEST_time_t_lt(testdateutc, 0)) {
         return 0;
     }
index 01535b85f8e7b2f86d1f9057e38a5b27222ed01d..c55c9a220e67cf9ce41269b57ffac52713268db5 100644 (file)
@@ -651,7 +651,7 @@ X509 *load_cert_pem(const char *file, OSSL_LIB_CTX *libctx);
 X509 *load_cert_der(const unsigned char *bytes, int len);
 STACK_OF(X509) *load_certs_pem(const char *file);
 X509_REQ *load_csr_der(const char *file, OSSL_LIB_CTX *libctx);
-time_t test_asn1_string_to_time_t(const char *asn1_string);
+int test_asn1_string_to_time_t(const char *asn1_string, time_t *out_time_t);
 int compare_with_reference_file(BIO *membio, const char *reffile);
 /*
  * Create an X509 from an array of strings.
index 490c85db03ffda6944836e33376ff39a686f7e7e..4f3df9eaf8ecdd2601ddb8b036d5dd022dfb6ab0 100644 (file)
@@ -6,87 +6,35 @@
  * in the file LICENSE in the source distribution or at
  * https://www.openssl.org/source/license.html
  */
-
-#include <stdio.h>
 #include <time.h>
-#include <openssl/asn1t.h>
-#include "../testutil.h"
 
-/*
- * tweak for Windows
- */
-#ifdef WIN32
-# define timezone _timezone
-#endif
+#include <openssl/asn1t.h>
+#include <openssl/posix_time.h>
 
-#if defined(__FreeBSD__) || defined(__wasi__) || \
-    (defined(__APPLE__) && !defined(OPENSSL_NO_APPLE_CRYPTO_RANDOM) && \
-     !(defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1050))
-# define USE_TIMEGM
-#endif
+#include "../testutil.h"
 
-time_t test_asn1_string_to_time_t(const char *asn1_string)
+int test_asn1_string_to_time_t(const char *asn1_string, time_t *out_time_t)
 {
+    int ret = 0;
     ASN1_TIME *timestamp_asn1 = NULL;
-    struct tm *timestamp_tm = NULL;
-#if defined(__DJGPP__)
-    char *tz = NULL;
-#elif !defined(USE_TIMEGM)
-    time_t timestamp_local;
-#endif
-    time_t timestamp_utc;
+    struct tm timestamp_tm;
 
     timestamp_asn1 = ASN1_TIME_new();
     if(timestamp_asn1 == NULL)
-        return -1;
-    if (!ASN1_TIME_set_string(timestamp_asn1, asn1_string))
-    {
-        ASN1_TIME_free(timestamp_asn1);
-        return -1;
-    }
+        goto err;
 
-    timestamp_tm = OPENSSL_malloc(sizeof(*timestamp_tm));
-    if (timestamp_tm == NULL) {
-        ASN1_TIME_free(timestamp_asn1);
-        return -1;
-    }
-    if (!(ASN1_TIME_to_tm(timestamp_asn1, timestamp_tm))) {
-        OPENSSL_free(timestamp_tm);
-        ASN1_TIME_free(timestamp_asn1);
-        return -1;
-    }
-    ASN1_TIME_free(timestamp_asn1);
+    if (!ASN1_TIME_set_string(timestamp_asn1, asn1_string))
+        goto err;
 
-#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);
+    if (!(ASN1_TIME_to_tm(timestamp_asn1, &timestamp_tm)))
+        goto err;
 
-    timestamp_utc = mktime(timestamp_tm);
+    if (!OPENSSL_timegm(&timestamp_tm, out_time_t))
+        goto err;
 
-    if (tz != NULL) {
-        setenv("TZ", tz, 1);
-        OPENSSL_free(tz);
-    } else {
-        unsetenv("TZ");
-    }
-#elif defined(USE_TIMEGM)
-    timestamp_utc = timegm(timestamp_tm);
-#else
-    timestamp_local = mktime(timestamp_tm);
-    timestamp_utc = timestamp_local - timezone;
-#endif
-    OPENSSL_free(timestamp_tm);
+    ret = 1;
 
-    return timestamp_utc;
+err:
+    ASN1_TIME_free(timestamp_asn1);
+    return ret;
 }