diff options
author | Florian Weimer <fweimer@redhat.com> | 2017-03-08 11:56:07 +0100 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2017-03-09 16:34:11 +0100 |
commit | c9611e6f0e631edbc043986e3030d57e70fafb90 (patch) | |
tree | 2f32a3542133ff6362d64ecd6c196830b8c376ab | |
parent | 9a56f8718341082d98cee9b245a02c8bf8c074da (diff) | |
download | glibc-c9611e6f0e631edbc043986e3030d57e70fafb90.zip glibc-c9611e6f0e631edbc043986e3030d57e70fafb90.tar.gz glibc-c9611e6f0e631edbc043986e3030d57e70fafb90.tar.bz2 |
Isolate global timezone variables in <time/time-variables.h>
This change makes it more explicit which subsystems access these
variables (which are thread safety hazards).
-rw-r--r-- | ChangeLog | 32 | ||||
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | include/time.h | 5 | ||||
-rw-r--r-- | locale/programs/ld-time.c | 7 | ||||
-rw-r--r-- | sysdeps/posix/gettimeofday.c | 3 | ||||
-rw-r--r-- | time/Makefile | 4 | ||||
-rw-r--r-- | time/Versions | 3 | ||||
-rw-r--r-- | time/dysize.c | 2 | ||||
-rw-r--r-- | time/getdate.c | 2 | ||||
-rw-r--r-- | time/gmtime.c | 1 | ||||
-rw-r--r-- | time/isleap.c | 27 | ||||
-rw-r--r-- | time/localtime.c | 1 | ||||
-rw-r--r-- | time/offtime.c | 4 | ||||
-rw-r--r-- | time/strftime_l.c | 26 | ||||
-rw-r--r-- | time/time-variables.h | 43 | ||||
-rw-r--r-- | time/time.h | 21 | ||||
-rw-r--r-- | time/tst-isleap.c | 40 | ||||
-rw-r--r-- | time/tzfile.c | 1 | ||||
-rw-r--r-- | time/tzset.c | 7 |
19 files changed, 190 insertions, 42 deletions
@@ -1,3 +1,35 @@ +2017-03-08 Florian Weimer <fweimer@redhat.com> + + Isolate global timezone variables in <time/time-variables.h>. + * time/time-variables.h: New file. + * time/time.h (__tzname, __daylight, __timezone): Remove private + declarations. + (tzname, daylight, timezone): Update comments. + (__isleap): Remove definition. + * include/time.h (__time_isleap): Declare. + * time/Makefile (routines): Add isleap. + (tests): Add tst-isleap. + * time/Versions (GLIBC_PRIVATE): Export __time_isleap. + * time/dysize.c (dysize): Call __time_isleap + instead of __isleap. + * time/getdate.c (check_mday): Likewise. + * time/offtime.c (__offtime): Likewise. + * time/gmtime.c: Include <time/time-variables.h>. + * time/localtime.c: Likewise. + * time/tzfile.c: Likewise. + * time/tzset.c: Likewise. + (__tzname, __daylight, __timezone): Turn into compat symbols. + (compute_change): Call __time_isleap instead of __isleap. + * time/strftime_l.c: Include <time/time-variables.h>. Reorganize + includes. + (tzname): Declare for !_LIBC only. + (__isleap): Define as __time_isleap. + * time/isleap.c: New file. + * time/tst-isleap.c: Likewise. + * locale/programs/ld-time.c (time_finish): Call __time_isleap + instead of __isleap. + * sysdeps/posix/gettimeofday.c: Include <time/time-variables.h>. + 2017-03-08 Yury Norov <ynorov@caviumnetworks.com> Zack Weinberg <zackw@panix.com> @@ -11,6 +11,9 @@ Version 2.26 transliteration tables are all updated to Unicode 9.0.0, using generator scripts contributed by Mike FABIAN (Red Hat). +* The private identifiers __daylight, __isleap, __timezone, __tzname have + been removed from the <time.h> header file. + Security related changes: [Add security related changes here] diff --git a/include/time.h b/include/time.h index 6badf0e..08454ef 100644 --- a/include/time.h +++ b/include/time.h @@ -3,6 +3,7 @@ #ifndef _ISOMAC # include <xlocale.h> +# include <stdbool.h> __BEGIN_DECLS @@ -31,8 +32,8 @@ struct tm; /* Defined in mktime.c. */ extern const unsigned short int __mon_yday[2][13] attribute_hidden; -/* Defined in localtime.c. */ -extern struct tm _tmbuf attribute_hidden; +bool __time_isleap (int year) internal_function; +libc_hidden_proto (__time_isleap) /* Defined in tzset.c. */ extern char *__tzstring (const char *string); diff --git a/locale/programs/ld-time.c b/locale/programs/ld-time.c index 32e9c41..03c219b 100644 --- a/locale/programs/ld-time.c +++ b/locale/programs/ld-time.c @@ -26,6 +26,7 @@ #include <wchar.h> #include <stdint.h> #include <sys/uio.h> +#include <time.h> #include <assert.h> @@ -353,7 +354,8 @@ No definition for %s category found"), "LC_TIME")); > days_per_month[time->era_entries[idx].start_date[1]]) || (time->era_entries[idx].start_date[1] == 2 && time->era_entries[idx].start_date[2] == 29 - && !__isleap (time->era_entries[idx].start_date[0]))) + && !__time_isleap (time->era_entries[idx] + .start_date[0]))) && !be_quiet) WITH_CUR_LOCALE (error (0, 0, _("\ %s: starting date is invalid in string %Zd in `era' field"), @@ -430,7 +432,8 @@ No definition for %s category found"), "LC_TIME")); > days_per_month[time->era_entries[idx].stop_date[1]]) || (time->era_entries[idx].stop_date[1] == 2 && time->era_entries[idx].stop_date[2] == 29 - && !__isleap (time->era_entries[idx].stop_date[0]))) + && !__time_isleap (time->era_entries[idx] + .stop_date[0]))) && !be_quiet) WITH_CUR_LOCALE (error (0, 0, _("\ %s: invalid stopping date in string %Zd in `era' field"), diff --git a/sysdeps/posix/gettimeofday.c b/sysdeps/posix/gettimeofday.c index 41a8217..9ed4c60 100644 --- a/sysdeps/posix/gettimeofday.c +++ b/sysdeps/posix/gettimeofday.c @@ -19,6 +19,9 @@ #include <time.h> #include <sys/time.h> +/* For __tzname, __timezone, __daylight. */ +#include <time/time-variables.h> + /* Get the current time of day and timezone information, putting it into *TV and *TZ. If TZ is NULL, *TZ is not filled. Returns 0 on success, -1 on errors. */ diff --git a/time/Makefile b/time/Makefile index 317c4d8..d21d90a 100644 --- a/time/Makefile +++ b/time/Makefile @@ -36,14 +36,14 @@ routines := offtime asctime clock ctime ctime_r difftime \ stime dysize timegm ftime \ getdate strptime strptime_l \ strftime wcsftime strftime_l wcsftime_l \ - timespec_get + timespec_get isleap 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-tzname tst-isleap include ../Rules diff --git a/time/Versions b/time/Versions index fd83818..24d1d2f 100644 --- a/time/Versions +++ b/time/Versions @@ -65,4 +65,7 @@ libc { GLIBC_2.16 { timespec_get; } + GLIBC_PRIVATE { + __time_isleap; + } } diff --git a/time/dysize.c b/time/dysize.c index feed19c..ffc5dd3 100644 --- a/time/dysize.c +++ b/time/dysize.c @@ -20,5 +20,5 @@ int dysize (int year) { - return __isleap (year) ? 366 : 365; + return __time_isleap (year) ? 366 : 365; } diff --git a/time/getdate.c b/time/getdate.c index 28ea482..bef9727 100644 --- a/time/getdate.c +++ b/time/getdate.c @@ -95,7 +95,7 @@ check_mday (int year, int mon, int mday) return 1; break; case 1: - if (mday >= 1 && mday <= (__isleap (year) ? 29 : 28)) + if (mday >= 1 && mday <= (__time_isleap (year) ? 29 : 28)) return 1; break; } diff --git a/time/gmtime.c b/time/gmtime.c index 049d551..1fc129b 100644 --- a/time/gmtime.c +++ b/time/gmtime.c @@ -17,6 +17,7 @@ <http://www.gnu.org/licenses/>. */ #include <time.h> +#include <time/time-variables.h> /* Return the `struct tm' representation of *T in UTC, using *TP to store the result. */ diff --git a/time/isleap.c b/time/isleap.c new file mode 100644 index 0000000..5f15709 --- /dev/null +++ b/time/isleap.c @@ -0,0 +1,27 @@ +/* Leap year detection. + Copyright (C) 2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <time.h> + +bool +internal_function +__time_isleap (int year) +{ + return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); +} +libc_hidden_def (__time_isleap) diff --git a/time/localtime.c b/time/localtime.c index 07dd67c..3a38cde 100644 --- a/time/localtime.c +++ b/time/localtime.c @@ -17,6 +17,7 @@ <http://www.gnu.org/licenses/>. */ #include <time.h> +#include <time/time-variables.h> /* The C Standard says that localtime and gmtime return the same pointer. */ struct tm _tmbuf; diff --git a/time/offtime.c b/time/offtime.c index 75a28fe..1729a96 100644 --- a/time/offtime.c +++ b/time/offtime.c @@ -57,7 +57,7 @@ __offtime (const time_t *t, long int offset, struct tm *tp) #define DIV(a, b) ((a) / (b) - ((a) % (b) < 0)) #define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400)) - while (days < 0 || days >= (__isleap (y) ? 366 : 365)) + while (days < 0 || days >= (__time_isleap (y) ? 366 : 365)) { /* Guess a corrected year, assuming 365 days per year. */ time_t yg = y + days / 365 - (days % 365 < 0); @@ -76,7 +76,7 @@ __offtime (const time_t *t, long int offset, struct tm *tp) return 0; } tp->tm_yday = days; - ip = __mon_yday[__isleap(y)]; + ip = __mon_yday[__time_isleap (y)]; for (y = 11; days < (long int) ip[y]; --y) continue; days -= ip[y]; diff --git a/time/strftime_l.c b/time/strftime_l.c index eb3efb8..2a13af5 100644 --- a/time/strftime_l.c +++ b/time/strftime_l.c @@ -33,28 +33,30 @@ # define MULTIBYTE_IS_FORMAT_SAFE 1 # define STDC_HEADERS 1 # include "../locale/localeinfo.h" -#endif -#if defined emacs && !defined HAVE_BCOPY -# define HAVE_MEMCPY 1 +# define __isleap(year) __time_isleap (year) +# include <time.h> +# include <time/time-variables.h> #endif #include <ctype.h> #include <sys/types.h> /* Some systems define `time_t' here. */ -#ifdef TIME_WITH_SYS_TIME -# include <sys/time.h> -# include <time.h> -#else -# ifdef HAVE_SYS_TIME_H +#ifndef _LIBC +# ifdef TIME_WITH_SYS_TIME # include <sys/time.h> -# else # include <time.h> +# else +# ifdef HAVE_SYS_TIME_H +# include <sys/time.h> +# else +# include <time.h> +# endif # endif -#endif -#if HAVE_TZNAME +# if HAVE_TZNAME extern char *tzname[]; -#endif +# endif +#endif /* !_LIBC */ /* Do multibyte processing if multibytes are supported, unless multibyte sequences are safe in formats. Multibyte sequences are diff --git a/time/time-variables.h b/time/time-variables.h new file mode 100644 index 0000000..b22e2dee --- /dev/null +++ b/time/time-variables.h @@ -0,0 +1,43 @@ +/* Global variables used by the time subsystem. + Copyright (C) 2017 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 + <http://www.gnu.org/licenses/>. */ + +/* This header should only be used within the time subsystem, but + there are some historic external references. The global variables + declared here cannot be accessed in a thread-safe manner. */ + +#ifndef TIME_VARIABLES_H +#define TIME_VARIABLES_H + +#include <stdbool.h> +#include <time.h> + +/* Global variables updated by tzset, localtime. Their counterparts + without the __ prefix are weak aliases of them. The static linker + will ensure that dynamically-linked programs which do not define + their own variable (without the __ prefix) use the variable from + glibc (which is updated by the glibc code through the __-prefixed + alias). If the application defines its own variable, it will be + separate from the glibc variable. */ +extern char *__tzname[2]; +extern int __daylight; +extern long int __timezone; + +/* Defined in localtime.c. Used by localtime and gmtime. */ +extern struct tm _tmbuf attribute_hidden; + +#endif /* TIME_VARIABLES_H */ diff --git a/time/time.h b/time/time.h index 7f98338..9383c09 100644 --- a/time/time.h +++ b/time/time.h @@ -160,16 +160,8 @@ extern char *ctime_r (const time_t *__restrict __timer, char *__restrict __buf) __THROW; #endif /* POSIX */ - -/* Defined in localtime.c. */ -extern char *__tzname[2]; /* Current timezone names. */ -extern int __daylight; /* If daylight-saving time is ever in use. */ -extern long int __timezone; /* Seconds west of UTC. */ - - #ifdef __USE_POSIX -/* Same as above. */ -extern char *tzname[2]; +extern char *tzname[2]; /* Current timezone names. */ /* Set time conversion information from the TZ environment variable. If TZ is not defined, a locale-dependent default is used. */ @@ -177,8 +169,8 @@ extern void tzset (void) __THROW; #endif #if defined __USE_MISC || defined __USE_XOPEN -extern int daylight; -extern long int timezone; +extern int daylight; /* If daylight-saving time is ever in use. */ +extern long int timezone; /* Seconds west of UTC. */ #endif #ifdef __USE_MISC @@ -187,13 +179,6 @@ extern long int timezone; extern int stime (const time_t *__when) __THROW; #endif - -/* Nonzero if YEAR is a leap year (every 4 years, - except every 100th isn't, and every 400th is). */ -#define __isleap(year) \ - ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) - - #ifdef __USE_MISC /* Miscellaneous functions many Unices inherited from the public domain localtime package. These are included only for compatibility. */ diff --git a/time/tst-isleap.c b/time/tst-isleap.c new file mode 100644 index 0000000..590a403 --- /dev/null +++ b/time/tst-isleap.c @@ -0,0 +1,40 @@ +/* Test leap year processing. + Copyright (C) 2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <time.h> +#include <support/check.h> + +static int +do_test (void) +{ + TEST_VERIFY (!__time_isleap (-100)); + TEST_VERIFY (__time_isleap (0)); + TEST_VERIFY (!__time_isleap (100)); + TEST_VERIFY (!__time_isleap (200)); + TEST_VERIFY (!__time_isleap (300)); + TEST_VERIFY (__time_isleap (400)); + TEST_VERIFY (!__time_isleap (1900)); + TEST_VERIFY (__time_isleap (1996)); + TEST_VERIFY (__time_isleap (2000)); + TEST_VERIFY (__time_isleap (2004)); + TEST_VERIFY (__time_isleap (2008)); + TEST_VERIFY (!__time_isleap (2100)); + return 0; +} + +#include <support/test-driver.c> diff --git a/time/tzfile.c b/time/tzfile.c index d412469..9290dc6 100644 --- a/time/tzfile.c +++ b/time/tzfile.c @@ -26,6 +26,7 @@ #include <sys/stat.h> #include <stdint.h> +#include <time/time-variables.h> #include <timezone/tzfile.h> int __use_tzfile; diff --git a/time/tzset.c b/time/tzset.c index 8868e9a..1fc3ac0 100644 --- a/time/tzset.c +++ b/time/tzset.c @@ -24,7 +24,10 @@ #include <stdlib.h> #include <string.h> #include <time.h> +#include <libc-symbols.h> +#include <shlib-compat.h> +#include <time/time-variables.h> #include <timezone/tzfile.h> char *__tzname[2] = { (char *) "GMT", (char *) "GMT" }; @@ -457,7 +460,7 @@ compute_change (tz_rule *rule, int year) add SECSPERDAY times the day number-1 to the time of January 1, midnight, to get the day. */ t += (rule->d - 1) * SECSPERDAY; - if (rule->d >= 60 && __isleap (year)) + if (rule->d >= 60 && __time_isleap (year)) t += SECSPERDAY; break; @@ -473,7 +476,7 @@ compute_change (tz_rule *rule, int year) unsigned int i; int d, m1, yy0, yy1, yy2, dow; const unsigned short int *myday = - &__mon_yday[__isleap (year)][rule->m]; + &__mon_yday[__time_isleap (year)][rule->m]; /* First add SECSPERDAY for each day in months before M. */ t += myday[-1] * SECSPERDAY; |