aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2017-03-08 11:56:07 +0100
committerFlorian Weimer <fweimer@redhat.com>2017-03-09 16:34:11 +0100
commitc9611e6f0e631edbc043986e3030d57e70fafb90 (patch)
tree2f32a3542133ff6362d64ecd6c196830b8c376ab
parent9a56f8718341082d98cee9b245a02c8bf8c074da (diff)
downloadglibc-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--ChangeLog32
-rw-r--r--NEWS3
-rw-r--r--include/time.h5
-rw-r--r--locale/programs/ld-time.c7
-rw-r--r--sysdeps/posix/gettimeofday.c3
-rw-r--r--time/Makefile4
-rw-r--r--time/Versions3
-rw-r--r--time/dysize.c2
-rw-r--r--time/getdate.c2
-rw-r--r--time/gmtime.c1
-rw-r--r--time/isleap.c27
-rw-r--r--time/localtime.c1
-rw-r--r--time/offtime.c4
-rw-r--r--time/strftime_l.c26
-rw-r--r--time/time-variables.h43
-rw-r--r--time/time.h21
-rw-r--r--time/tst-isleap.c40
-rw-r--r--time/tzfile.c1
-rw-r--r--time/tzset.c7
19 files changed, 190 insertions, 42 deletions
diff --git a/ChangeLog b/ChangeLog
index ba57667..e8a8fd5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
diff --git a/NEWS b/NEWS
index d87e9ce..40ad8b2 100644
--- a/NEWS
+++ b/NEWS
@@ -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;