diff options
Diffstat (limited to 'time')
-rw-r--r-- | time/Makefile | 62 | ||||
-rw-r--r-- | time/tst-clock_gettime-time64.c | 1 | ||||
-rw-r--r-- | time/tst-clock_gettime.c | 184 | ||||
-rw-r--r-- | time/tst-gettimeofday-time64.c | 1 | ||||
-rw-r--r-- | time/tst-gettimeofday.c | 93 | ||||
-rw-r--r-- | time/tst-time-time64.c | 1 | ||||
-rw-r--r-- | time/tst-time.c | 51 | ||||
-rw-r--r-- | time/tst-tzfile-fault.c | 44 | ||||
-rw-r--r-- | time/tzfile.c | 5 |
9 files changed, 431 insertions, 11 deletions
diff --git a/time/Makefile b/time/Makefile index 5b541fb9d3..4bfb208110 100644 --- a/time/Makefile +++ b/time/Makefile @@ -42,30 +42,70 @@ routines := offtime asctime clock ctime ctime_r difftime \ aux := era alt_digit lc-time-cleanup -tests := test_time clocktest tst-posixtz tst-strptime tst_wcsftime \ - tst-getdate tst-mktime tst-mktime2 tst-ftime_l tst-strftime \ - tst-mktime3 tst-strptime2 bug-asctime bug-asctime_r bug-mktime1 \ - tst-strptime3 bug-getdate1 tst-strptime-whitespace tst-ftime \ - tst-tzname tst-y2039 bug-mktime4 tst-strftime2 tst-strftime3 \ - tst-clock tst-clock2 tst-clock_nanosleep tst-cpuclock1 \ - tst-adjtime tst-ctime tst-difftime tst-mktime4 tst-clock_settime \ - tst-settimeofday tst-itimer tst-gmtime tst-timegm \ - tst-timespec_get tst-timespec_getres tst-strftime4 +tests := \ + bug-asctime \ + bug-asctime_r \ + bug-getdate1 \ + bug-mktime1 \ + bug-mktime4 \ + clocktest \ + test_time \ + tst-adjtime \ + tst-clock \ + tst-clock2 \ + tst-clock_gettime \ + tst-clock_nanosleep \ + tst-clock_settime \ + tst-cpuclock1 \ + tst-ctime \ + tst-difftime \ + tst-ftime \ + tst-ftime_l \ + tst-getdate \ + tst-gettimeofday \ + tst-gmtime \ + tst-itimer \ + tst-mktime \ + tst-mktime2 \ + tst-mktime3 \ + tst-mktime4 \ + tst-posixtz \ + tst-settimeofday \ + tst-strftime \ + tst-strftime2 \ + tst-strftime3 \ + tst-strftime4 \ + tst-strptime \ + tst-strptime-whitespace \ + tst-strptime2 \ + tst-strptime3 \ + tst-time \ + tst-timegm \ + tst-timespec_get \ + tst-timespec_getres \ + tst-tzfile-fault \ + tst-tzname \ + tst-y2039 \ + tst_wcsftime \ + # tests tests-time64 := \ tst-adjtime-time64 \ tst-clock-time64 \ tst-clock2-time64 \ + tst-clock_gettime-time64 \ tst-clock_nanosleep-time64 \ tst-clock_settime-time64 \ tst-cpuclock1-time64 \ tst-ctime-time64 \ tst-difftime-time64 \ + tst-gettimeofday-time64 \ tst-gmtime-time64 \ tst-itimer-time64 \ tst-mktime4-time64 \ tst-settimeofday-time64 \ tst-strftime4-time64 \ + tst-time-time64 \ tst-timegm-time64 \ tst-timespec_get-time64 \ tst-timespec_getres-time64 \ @@ -87,6 +127,8 @@ $(objpfx)tst-strftime2.out: $(gen-locales) $(objpfx)tst-strftime3.out: $(gen-locales) endif +$(objpfx)tst-clock_gettime: $(librt) +$(objpfx)tst-clock_gettime-time64: $(librt) $(objpfx)tst-clock_nanosleep: $(librt) $(objpfx)tst-clock_nanosleep-time64: $(librt) @@ -110,3 +152,5 @@ tst-tzname-ENV = TZDIR=${common-objpfx}timezone/testdata CPPFLAGS-tst-tzname.c += -DTZDEFRULES='"$(posixrules-file)"' bug-getdate1-ARGS = ${objpfx}bug-getdate1-fmt + +tst-tzfile-fault-ENV = GLIBC_TUNABLES=glibc.rtld.enable_secure=1 diff --git a/time/tst-clock_gettime-time64.c b/time/tst-clock_gettime-time64.c new file mode 100644 index 0000000000..5b215d11f8 --- /dev/null +++ b/time/tst-clock_gettime-time64.c @@ -0,0 +1 @@ +#include "tst-clock_gettime.c" diff --git a/time/tst-clock_gettime.c b/time/tst-clock_gettime.c new file mode 100644 index 0000000000..51f24c0be2 --- /dev/null +++ b/time/tst-clock_gettime.c @@ -0,0 +1,184 @@ +/* Test clock_gettime function. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <stdbool.h> +#include <stdio.h> +#include <time.h> + +#include <support/check.h> +#include <support/test-driver.h> +#include <support/xsignal.h> + +/* Compare two struct timespec values, returning a value -1, 0 or 1. */ + +int +compare_timespec (const struct timespec *tv1, const struct timespec *tv2) +{ + if (tv1->tv_sec < tv2->tv_sec) + return -1; + if (tv1->tv_sec > tv2->tv_sec) + return 1; + if (tv1->tv_nsec < tv2->tv_nsec) + return -1; + if (tv1->tv_nsec > tv2->tv_nsec) + return 1; + return 0; +} + +struct test_clockid +{ + clockid_t clockid; + const char *name; + bool is_cputime; + bool fail_ok; +}; + +#define CLOCK(clockid) { clockid, # clockid, false, false } +#define CLOCK_CPU(clockid) { clockid, # clockid, true, false } +#define CLOCK_FAIL_OK(clockid) { clockid, # clockid, false, true } + +static const struct test_clockid clocks[] = + { + CLOCK (CLOCK_REALTIME), +#ifdef CLOCK_MONOTONIC + CLOCK (CLOCK_MONOTONIC), +#endif +#ifdef CLOCK_PROCESS_CPUTIME_ID + CLOCK_CPU (CLOCK_PROCESS_CPUTIME_ID), +#endif +#ifdef CLOCK_THREAD_CPUTIME_ID + CLOCK_CPU (CLOCK_THREAD_CPUTIME_ID), +#endif +#ifdef CLOCK_MONOTONIC_RAW + CLOCK (CLOCK_MONOTONIC_RAW), +#endif +#ifdef CLOCK_REALTIME_COARSE + CLOCK (CLOCK_REALTIME_COARSE), +#endif +#ifdef CLOCK_MONOTONIC_COARSE + CLOCK (CLOCK_MONOTONIC_COARSE), +#endif +#ifdef CLOCK_BOOTTIME + CLOCK (CLOCK_BOOTTIME), +#endif +#ifdef CLOCK_REALTIME_ALARM + CLOCK_FAIL_OK (CLOCK_REALTIME_ALARM), +#endif +#ifdef CLOCK_BOOTTIME_ALARM + CLOCK_FAIL_OK (CLOCK_BOOTTIME_ALARM), +#endif +#ifdef CLOCK_TAI + CLOCK (CLOCK_TAI), +#endif + }; + + +volatile int sigalrm_received; + +void +handle_sigalrm (int sig) +{ + sigalrm_received = 1; +} + +int +do_test (void) +{ + /* Verify that the calls to clock_gettime succeed, that the time does + not decrease, and that time returns a truncated (not rounded) + version of the time. */ + for (size_t i = 0; i < sizeof clocks / sizeof clocks[0]; i++) + { + printf ("testing %s\n", clocks[i].name); + struct timespec ts1, ts2, ts3; + int ret; + time_t t1; + t1 = time (NULL); + TEST_VERIFY_EXIT (t1 != (time_t) -1); + ret = clock_gettime (clocks[i].clockid, &ts1); + if (clocks[i].fail_ok && ret == -1) + { + printf ("failed (OK for this clock): %m\n"); + continue; + } + TEST_VERIFY_EXIT (ret == 0); + if (clocks[i].clockid == CLOCK_REALTIME) + TEST_VERIFY (t1 <= ts1.tv_sec); + TEST_VERIFY (ts1.tv_nsec >= 0); + TEST_VERIFY (ts1.tv_nsec < 1000000000); + ret = clock_gettime (clocks[i].clockid, &ts2); + TEST_VERIFY_EXIT (ret == 0); + TEST_VERIFY (compare_timespec (&ts1, &ts2) <= 0); + TEST_VERIFY (ts2.tv_nsec >= 0); + TEST_VERIFY (ts2.tv_nsec < 1000000000); + /* Also verify that after sleeping, the time returned has + increased. Repeat several times to verify that each time, + the time from the time function is truncated not rounded. + For CPU time clocks, the time spent spinning on the CPU, and + so whether we end in the later half of a second, is not + predictable; thus, only test once for those clocks. */ + const struct timespec duration = { .tv_nsec = 100000000 }; + for (int j = 0; j < 5; j++) + { + if (clocks[i].is_cputime) + { + timer_t timer; + ret = timer_create (CLOCK_PROCESS_CPUTIME_ID, NULL, &timer); + TEST_VERIFY_EXIT (ret == 0); + sigalrm_received = 0; + xsignal (SIGALRM, handle_sigalrm); + struct itimerspec t = + { .it_value = + { + .tv_sec = 0, + .tv_nsec = 200000000 + } + }; + ret = timer_settime (timer, 0, &t, NULL); + TEST_VERIFY_EXIT (ret == 0); + while (sigalrm_received == 0) + ; + xsignal (SIGALRM, SIG_DFL); + ret = timer_delete (timer); + TEST_VERIFY_EXIT (ret == 0); + } + else + { + ret = nanosleep (&duration, NULL); + TEST_VERIFY_EXIT (ret == 0); + } + t1 = time (NULL); + TEST_VERIFY_EXIT (t1 != (time_t) -1); + ret = clock_gettime (clocks[i].clockid, &ts3); + TEST_VERIFY_EXIT (ret == 0); + TEST_VERIFY (compare_timespec (&ts2, &ts3) < 0); + if (clocks[i].clockid == CLOCK_REALTIME) + TEST_VERIFY (t1 <= ts3.tv_sec); + TEST_VERIFY (ts3.tv_nsec >= 0); + TEST_VERIFY (ts3.tv_nsec < 1000000000); + ts2 = ts3; + if (clocks[i].is_cputime) + break; + } + } + return 0; +} + +#define TIMEOUT 60 + +#include <support/test-driver.c> diff --git a/time/tst-gettimeofday-time64.c b/time/tst-gettimeofday-time64.c new file mode 100644 index 0000000000..6c08761ef9 --- /dev/null +++ b/time/tst-gettimeofday-time64.c @@ -0,0 +1 @@ +#include "tst-gettimeofday.c" diff --git a/time/tst-gettimeofday.c b/time/tst-gettimeofday.c new file mode 100644 index 0000000000..978ae28587 --- /dev/null +++ b/time/tst-gettimeofday.c @@ -0,0 +1,93 @@ +/* Test gettimeofday function. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <sys/time.h> +#include <time.h> + +#include <support/check.h> +#include <support/test-driver.h> + +/* Compare two struct timeval values, returning a value -1, 0 or 1. */ + +int +compare_timeval (const struct timeval *tv1, const struct timeval *tv2) +{ + if (tv1->tv_sec < tv2->tv_sec) + return -1; + if (tv1->tv_sec > tv2->tv_sec) + return 1; + if (tv1->tv_usec < tv2->tv_usec) + return -1; + if (tv1->tv_usec > tv2->tv_usec) + return 1; + return 0; +} + +int +do_test (void) +{ + struct timeval tv1, tv2, tv3; + int ret; + time_t t1; + /* Verify that the calls to gettimeofday succeed, that the time does + not decrease, and that time returns a truncated (not rounded) + version of the time. */ + t1 = time (NULL); + TEST_VERIFY_EXIT (t1 != (time_t) -1); + ret = gettimeofday (&tv1, NULL); + TEST_VERIFY_EXIT (ret == 0); + TEST_VERIFY (t1 <= tv1.tv_sec); + TEST_VERIFY (tv1.tv_usec >= 0); + TEST_VERIFY (tv1.tv_usec < 1000000); + ret = gettimeofday (&tv2, NULL); + TEST_VERIFY_EXIT (ret == 0); + TEST_VERIFY (compare_timeval (&tv1, &tv2) <= 0); + TEST_VERIFY (tv2.tv_usec >= 0); + TEST_VERIFY (tv2.tv_usec < 1000000); + /* Also verify that after sleeping, the time returned has increased. + Repeat several times to verify that each time, the time from the + time function is truncated not rounded. */ + const struct timespec duration = { .tv_nsec = 100000000 }; + for (int i = 0; i < 10; i++) + { + ret = nanosleep (&duration, NULL); + TEST_VERIFY_EXIT (ret == 0); + t1 = time (NULL); + TEST_VERIFY_EXIT (t1 != (time_t) -1); + ret = gettimeofday (&tv3, NULL); + TEST_VERIFY_EXIT (ret == 0); + TEST_VERIFY (compare_timeval (&tv2, &tv3) < 0); + TEST_VERIFY (t1 <= tv3.tv_sec); + TEST_VERIFY (tv3.tv_usec >= 0); + TEST_VERIFY (tv3.tv_usec < 1000000); + tv2 = tv3; + } + /* Also test with the obsolete tz argument not being NULL. */ + struct timezone tz = { 0 }; + t1 = time (NULL); + TEST_VERIFY_EXIT (t1 != (time_t) -1); + ret = gettimeofday (&tv3, &tz); + TEST_VERIFY_EXIT (ret == 0); + TEST_VERIFY (t1 <= tv3.tv_sec); + TEST_VERIFY (compare_timeval (&tv2, &tv3) <= 0); + TEST_VERIFY (tv3.tv_usec >= 0); + TEST_VERIFY (tv3.tv_usec < 1000000); + return 0; +} + +#include <support/test-driver.c> diff --git a/time/tst-time-time64.c b/time/tst-time-time64.c new file mode 100644 index 0000000000..30e8d3c86e --- /dev/null +++ b/time/tst-time-time64.c @@ -0,0 +1 @@ +#include "tst-time.c" diff --git a/time/tst-time.c b/time/tst-time.c new file mode 100644 index 0000000000..7f24bed353 --- /dev/null +++ b/time/tst-time.c @@ -0,0 +1,51 @@ +/* Test time function. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <time.h> +#include <unistd.h> + +#include <support/check.h> +#include <support/test-driver.h> + +int +do_test (void) +{ + time_t t1, t2, t3, t4, t5, t6; + /* Verify that the calls to time succeed, that the value returned + directly equals that returned through the pointer passed, and + that the time does not decrease. */ + t1 = time (&t2); + TEST_VERIFY_EXIT (t1 != (time_t) -1); + TEST_VERIFY (t1 == t2); + t3 = time (NULL); + TEST_VERIFY_EXIT (t3 != (time_t) -1); + TEST_VERIFY (t3 >= t1); + /* Also verify that after sleeping, the time returned has + increased. */ + sleep (2); + t4 = time (&t5); + TEST_VERIFY_EXIT (t4 != (time_t) -1); + TEST_VERIFY (t4 == t5); + TEST_VERIFY (t4 > t3); + t6 = time (NULL); + TEST_VERIFY_EXIT (t6 != (time_t) -1); + TEST_VERIFY (t6 >= t4); + return 0; +} + +#include <support/test-driver.c> diff --git a/time/tst-tzfile-fault.c b/time/tst-tzfile-fault.c new file mode 100644 index 0000000000..105c2ac7ce --- /dev/null +++ b/time/tst-tzfile-fault.c @@ -0,0 +1,44 @@ +/* Attempt to trigger fault with very short TZ variable (bug 31931). + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + + +#include <support/next_to_fault.h> +#include <stdlib.h> +#include <time.h> +#include <string.h> + +static char tz[] = "TZ=/"; + +static int +do_test (void) +{ + struct support_next_to_fault ntf + = support_next_to_fault_allocate (sizeof (tz)); + memcpy (ntf.buffer, tz, sizeof (tz)); + putenv (ntf.buffer); + + tzset (); + + /* Avoid dangling pointer in environ. */ + putenv (tz); + support_next_to_fault_free (&ntf); + + return 0; +} + +#include <support/test-driver.c> diff --git a/time/tzfile.c b/time/tzfile.c index 4147539964..964a9b7f12 100644 --- a/time/tzfile.c +++ b/time/tzfile.c @@ -134,8 +134,9 @@ __tzfile_read (const char *file, size_t extra, char **extrap) and which is not the system wide default TZDEFAULT. */ if (__libc_enable_secure && ((*file == '/' - && memcmp (file, TZDEFAULT, sizeof TZDEFAULT) - && memcmp (file, default_tzdir, sizeof (default_tzdir) - 1)) + && strcmp (file, TZDEFAULT) != 0 + && (strncmp (file, default_tzdir, sizeof (default_tzdir) - 1) + != 0)) || strstr (file, "../") != NULL)) /* This test is certainly a bit too restrictive but it should catch all critical cases. */ |