Problem reported by Joseph Myers in:
https://gcc.gnu.org/ml/gcc-patches/2015-05/msg00704.html
* localtime.c (detzcode, detzcode64): Don't rely on
undefined behavior with left shift into sign bit.
Port better to non-2's-complement machines.
* private.h (TWOS_COMPLEMENT, MAXVAL, MINVAL): New macros.
* private.h (time_t_min, time_t_max):
* zic.c (min_time, max_time): Use them to avoid undefined behavior.
* zdump.c (atime_shift): New constant.
(absolute_min_time, absolute_max_time):
Use it to avoid undefined behavior.
* localtime.c (settzname): Move scrubbing into ...
(scrub_abbrs): ... this new function.
(zoneinit): Use it here, rather than in settzname.
* NEWS: Document this.
Christos Zoulas reported a crash due to a tzsetlcl failure to
initialize data in some places, and requested that errno be set
when time functions fail; see:
http://mm.icann.org/pipermail/tz/2014-October/021754.html
While fixing this in a different way, I noticed and fixed another
instance of undefined behavior when read returns a too-small value.
* NEWS: Document this.
* localtime.c (union input_buffer): Rename from u_t.
(union input_buffer, union local_storage):
Move to top level so that two functions can use them.
(tzloadbody): New function, with most of the body of the old tzload.
Check for short reads that leave uninitialized buffers behind.
Define a new constant TZHEADSIZE for this, and use it to simplify
other code that already uses the concept.
(tzload): Use it. This removes the need for gotos. Return an errno
value; all callers changed.
(zoneinit): Return bool, not struct state *. Assume SP is nonnull.
All callers changed.
(zoneinit, tzalloc): Set errno on failure.
(tzsetlcl): Don't crash if zoneinit fails.
* private.h (ENAMETOOLONG): Define if not already defined.
See: http://mm.icann.org/pipermail/tz/2014-October/021692.html
* asctime.c (asctime_r): Remove now-unnecessary EOVERFLOW ifdef.
* localtime.c (timesub): Set errno to EOVERFLOW on overflow.
POSIX requires this.
(ctime, ctime_r): Return NULL instead of having undefined behavior
when the time stamp is out of struct tm range. NetBSD does this,
the standards allow it, and it's nicer for users.
* private.h (EOVERFLOW): Default to EINVAL on ancient hosts that lack it.
* NEWS: Document this.
in: http://mm.icann.org/pipermail/tz/2014-October/021684.html
* localtime.c (tzload): Use ssize_t, not int. Redo comparison to
avoid the need for an ssize_t value less than -1, which POSIX does
not guarantee. Use memmove so that we needn't worry about an
ssize_t index.
(tzparse): Remove static always-zero var. Initialized fields
to zero by hand instead.
(zoneinit): Initialized more fields, to avoid undefined behavior
in tzalloc.
(leapcorr): Fix bug, a stray initialization of a local variable.
* Makefile: Add comment about ssize_t.
* NEWS: Document the above.
* localtime.c (localsub): Don't bother updating 'tzname' again
when localtime is GMT, as tzset's value should be fine. When
updating 'tzname', also update 'timezone' and 'altzone'
consistently, on platforms that define the latter two vars.
* NEWS: Document this.
We don't know of any problems with the previous code on practical
platforms, but it's safer to be portable.
Problem reported by Andy Heninger in:
http://mm.icann.org/pipermail/tz/2014-September/021599.html
* localtime.c (VOLATILE): Remove. All uses removed.
(gmtcheck): Don't access gmt_is_set until we have the lock.
This may be significantly slower, but it's safer.
(localtime_tzset): Likewise. This change isn't significantly
slower, though; it's more of a refactoring.
* NEWS: Document this.
In 2014g, localtime and mktime set tzname[0] and tzname[1] as if by
tzset, regardless of the requested time stamp. In 2014f and earlier,
localtime and mktime then set tzname[0] or tzname[1] to a time zone
appropriate for the time stamp in question.
Although both behaviors conform to POSIX, the 2014f behavior is
better because it lets a single-threaded application discover the
time zone abbreviation appropriate for the just-queried time stamp
even on platforms that lack TM_ZONE. The 2014f-and-earlier zdump
relies on the 2014f library behavior on these platforms.
Problem reported by Tim Parenti in:
http://mm.icann.org/pipermail/tz/2014-September/021585.html
* localtime.c (localsub): Treat a nonzero offset value
as a request to set tzname on success. All callers changed.
(localtime_rz, mktime_z): Define only if NETBSD_INSPIRED,
as they're no longer needed otherwise.
(localtime_tzset): Invert sense of third arg from SKIP_TZSET
to SETTZ. New arg SETNAME. All callers changed.
(localtime): Request tzname to be set on success.
(mktime_tzname): New function, with most of the previous
contents of mktime_z.
(mktime_z, mktime): Use it.
* NEWS: Document the above.
Suggested by Jonathan Lennox in:
http://mm.icann.org/pipermail/tz/2014-August/021529.html
* localtime.c (tzalloc): Treat NULL argument like tzsetwall.
(tzsetwall_unlocked): Remove, replacing with ...
(tzsetlcl): New function, which merges the old tzsetwall and
tzset_unlocked.
(zoneinit): Treat a null NAME like tzsetwall.
(tzsetwall, tzset_unlocked): Rewrite to use tzsetlcl.
* NEWS: Document this.
These don't fix any bugs, but make the recently-introduced 'bool'
code easier to follow.
* localtime.c (gmtcheck): Move gmt_is_set's definition here,
since it's used only here.
(localtime_r): Explicitly convert integer to boolean rather
than relying on C99 semantics.
Problem reported by Alan Barrett in:
http://mm.icann.org/pipermail/tz/2014-August/021518.html
* localtime.c (zoneinit): Use UTC if !name.
That way, tzalloc(NULL) returns UTC, as in NetBSD.
(mktime_z): Use UTC if !sp.
* NEWS: Document this.
* Makefile, NEWS: Document this.
* localtime.c (NETBSD_INSPIRED_EXTERN): New macro.
(zoneinit): New function, with tzset_unlocked's internals.
(tzset_unlocked): Use it.
(tzalloc, tzfree) [NETBSD_INSPIRED]: New functions.
(localsub, gmtsub, time2sub, time2, time1, leapcorr):
New time zone argument. All uses changed.
(localsub, gmtsub): Cast to char *, since the time zone argument
is a pointer-to-const.
(localtime_rz): New function, with localtime_tzset's internals.
(localtime_tzset): Use it.
(mktime_z): New function, with mktime's internals.
(mktime): Use it.
(leapcorr): Pass time_t by value, not by reference.
(time2posix_z): New function, with time2posix's internals.
(time2posix): Use it. Omit unnecessary local.
(posix2time_z): New function, with posix2time's internals.
(posix2time): Use it.
* private.h (NETBSD_INSPIRED): Default to 1.
(localtime_rz, mktime_z, timezone_t, strftime, tzalloc, tzfree):
Define if NETBSD_INSPIRED is defined.
Use macros to avoid any clashes with <time.h>.
(posiztime_z, time2posix_z): Likewise, but only if
STD_INSPIRED is also defined.
* localtime.c (SMALLEST): New macro.
(time2sub) [TM_GMTOFF && !UNINIT_TRAP]:
If the UTC offset doesn't match the request, try the requested offset.
This catches a problem caught by -DTYPECHECK with a time stamp
near a transition from LMT to standard time, where both sides of
the transition have tm_isdst == 0. If !defined TM_GMTOFF ||
UNINIT_TRAP you're out of luck: mktime will still conform
to its spec but it'll be more likely to guess wrong on these
ambiguous inputs.
* private.h (UNINIT_TRAP): New macro that defaults to 0.
* Makefile, NEWS: Document this.
The Mach project has been inactive for decades,
and mktime has evidently replaced gtime.
* Makefile: Remove comment about CMUCS.
* localtime.c (gtime) [CMUCS]: Remove.
* NEWS: Document the above.
* localtime.c (tzload): Avoid undefined behavior on integer overflow
when reading a file containing integers out of machine range.
Simplify some of the existing overflow checking.
Handle out-of-range leap-second transitions similarly to the
way we now handle out-of-range ordinary transitions.
* NEWS: Document this and other recent fixes.
* localtime.c (tzload): On platforms where time_t is unsigned,
don't mishandle zones that contain leap seconds but no ordinary
transitions after 1970. This problem can be reproduced by running
'zdump -v right/Asia/Dubai' on a platform where time_t is an
unsigned 32-bit integer.
Although the cast to void in usage like '(void) printf ("Hello")'
may have been helpful decades ago when Lint Was Your Friend,
nowadays such casts are not helpful. The tz code is currently not
consistent about this: sometimes the casts are present, and
sometimes absent. As they make the code harder to read, let's
remove them.
* asctime.c, date.c, ialloc.c, localtime.c, strftime.c, zdump.c, zic.c:
Don't cast calls to 'void'.
* localtime.c [THREAD_SAFE]: Include pthread.h.
(VOLATILE): New macro.
(locallock) [THREAD_SAFE]: New static var.
(lock, unlock): New functions.
(lcl_is_set, gmt_is_set): Now VOLATILE.
(tzsetwall): Move cleaned-up guts to new function tzsetwall_unlocked,
for which this is now merely a locking wrapper.
(tzset): Similarly, for new function tzset_unlocked.
(localsub): Don't set tzname here; that's not thread-safe.
This change can lose information on hosts without TM_ZONE,
but there is no reliable way to fix that in a thread-safe way.
(localtime_tzset): New function, which does proper locking.
(localtime, localtime_r): Use it.
(gmtsub): Do not worry about initializing gmtptr, as that's now
the caller's responsibility.
(gmtime): Reimplement in terms of gmtime_r.
(timegm): Reimplement in terms of timeoff.
(gmtime_r, offtime, mktime, timeoff, time2posix, posix2time):
Lock at start and unlock at end.
* Makefile, NEWS: Document this.
* localtime.c (LOCALTIME_IMPLEMENTATION): New macro.
(time) [time_tz]: Move here from private.h, and make external.
* private.h (sys_time) [time_tz]: Define only if
LOCALTIME_IMPLEMENTATION, so that the code doesn't define an unused
static function sys_time that the compiler might complain about.
(time) [time_tz]: Move to localtime.c.
* NEWS: Document this.
by removing prototypes that aren't needed, and by removing names
of arguments. This will make future changes simpler and easier to
follow.
* NEWS: Document this.
These changes pacify gcc 4.8.2-19ubuntu1 on Ubuntu 14.04,
and take advantage of recently-added GCC options when compiling
with GCC_DEBUG_FLAGS.
* Makefile (GCC_DEBUG_FLAGS): Add -Wdeclaration-after-statement,
-Wjump-misses-init, -Wsuggest-attribute=format.
* date.c (copyright, sccsid):
* strftime.c (sccsid):
Remove unused vars.
* date.c (main):
* localtime.c (tzparse):
Remove no-longer-needed uses of INITIALIZE; GCC is smart enough to
figure these out on its own now.
* localtime.c (gmtsub): Redo initialization of gmt_is_set to pacify GCC.
Retry malloc next time even if it failed this time.
* private.h, zdump.c (GNUC_or_lint): Remove, as it provoked a GCC
diagnostic about unused macros in some cases. Instead, just use
'lint'. All uses removed.
(TZ_DOMAIN): Don't define unless needed, as otherwise it provokes
a GCC diagnostic about unused macros.
* private.h (INITIALIZE): Simplify accordingly.
* NEWS: Document this.
Most of this patch is to commentary, to distinguish better among
the similar characters hyphen '-', minus sign '−', en dash '–' (used
for ranges), and em dash '—'. Render ordinary dashes in text as
spaced en dashes, as this gives better-looking results in monospaced
fonts.
* yearistype.sh, zic.c: Reword diagnostics so that they do not use
hyphens as if they were dashes. Since we are sticking to ASCII in
programs, we can't use proper dashes in diagnostics.
This was appropriate before Unicode, where "`" and "'" often balanced
in visual output, but that's been obsolete for a while.
Overall, single-quote 'like this' instead of `like this', and
double-quote "like this" or (in typeset output) “like this”
instead of ``like this''. While we're at it, fix some glitches
with hyphens versus minus versus en dash versus em dash.
* Makefile ($(MANTXTS)): Use UTF-8 locale to produce *.txt output.
* checktab.awk, tzselect.ksh:
Quote 'like this' in diagnostics, instead of `like this'.
* date.1, newctime.3, newtzset.3, time2posix.3, zic.8 (q, lq, rq):
New macros. Use them for better double-quoting in output.
* workman.sh: Tell Perl that its stdin and stdout are UTF-8.
* NEWS: Document this.
* localtime.c (time1): Shrink size of 'types' local back down
from TZ_MAX_TIMES to TZ_MAX_TYPES. The smaller value suffices,
since nseen can grow to at most TZ_MAX_TYPES. (Thanks to
Arthur David Olson.)
* NEWS: Remove mention of non-fix.
* localtime.c (tzload) [ALL_STATE]:
Redo to keep the stack frame tiny.
(time1): Shrink sizes of local arrays so that this stack frame
doesn't take much more than about TZ_MAX_TIMES bytes total.
* Makefile (GCC_DEBUG_FLAGS): Add -Wno-address and -Wno-cast-qual.
Otherwise, GCC 4.8.1 complains about some of the following changes.
* localtime.c (wildabbr): Now const. This is a tiny bit more
efficient, POSIX allows it, and the ALL_STATE simplifications
below make use of it. All uses changed to cast if needed.
(settzname, tzload, localsub, gmtsub, timesub, time2sub, time1):
Protect less code with ALL_STATE; this is simpler and doesn't
change behavior (or, these days, efficiency).
(time1): Simplify the PCTS ifdef, and explain what PCTS is.
* localtime.c (tzload) [ALL_STATE]: Initialize sp->goback
and sp->goahead even if memory allocation fails.
(tzload, tzsetwall, tzset, gmtsub) [ALL_STATE]:
Use malloc, not calloc, since the !ALL_STATE code has to
work with reused storage anyway.
* NEWS: Document Logan Chien's fix.
This fixes a longstanding test-case failure with
'make check_time_t_alternatives'.
* localtime.c (detzcode64): Return int_fast64_t, not time_t,
for the benefit of platforms where time_t is narrower than 64 bits.
The distinction matters if time_t is 32-bit unsigned.
Simplify the shifts and masks.
(tzload): Fix the check for overflow when storing the loaded time
value into a time_t object. The old code didn't work when
time_t was an unsigned 32-bit quantity.
(transtime): Return the offset from the start of the year,
not the offset since the Epoch, since the former cannot overflow
but the latter can. Caller changed.
(tzparse): Check for overflow more carefully when computing
time stamps. The old code didn't work for 32-bit unsigned values,
in unusual situations such as Pacific/Fiji and Pacific/Auckland
for times past 2038.
(increment_overflow_time): New function.
Reported by Elliott Hughes in
<http://mm.icann.org/pipermail/tz/2013-September/020376.html>.
* localtime.c (timezone) [USG_COMPAT]:
(altzone) [ALTZONE]: Now long, not time_t.
* strftime.c (_fmt): Use long, not int, to store timezone.
* NEWS: Document this.
Problem reported by Zefram in
<http://mm.icann.org/pipermail/tz/2013-September/020059.html>.
* localtime.c (tzparse): Elide simultaneous entries out of and
into DST if DST goes for an hour more than a year (actually, for
more than the DST offset more than a year). Since this
optimization can elide all entries, avoid looping forever looking
for entries that will never arrive. While we're at it, fix
another portability bug where the code assumed wraparound on
signed integer overflow.
* newtzset.3, tzfile.5: Mention that as an extension to POSIX,
if DST covers the entire year plus the DST offset, it's assumed to
be in effect all year. Give an example.
* zic.c (stringrule): Omit the "J" in January and February,
as this can save a byte or two in the output.
(rule_cmp): New function.
(stringzone): Do a better job of constructing the standard-time
abbreviation when there is perpetual DST. Defer to the new
stringrule to construct the times for perpetual DST.
Fix bug noted by Zefram, which caused a stray hour of standard
time to be inserted in an otherwise perpetual DST.
Previously, this code generated "WARST4WARST,J1/0,J365/24"
for the San Luis example; now it generates "WART4WARST,0/0,J365/25".
This implements a suggestion by Arthur David Olson.
Without this change, zic -v diagnoses problems with several zones
where it cannot compute a POSIX-equivalent TZ setting for time
stamps past 2038, which means these time stamps may be mishandled.
This entails a minor change to the binary tz file format, to allow
a minor extension to the POSIX TZ setting in the binary file,
instead of requiring a pure POSIX TZ setting. The zones fixed by
this change are America/Godthab, America/Santiago, Antarctica/Palmer,
Asia/Gaza, Asia/Hebron, Asia/Jerusalem, Pacific/Easter, and
Pacific/Fiji. The only zone that remains unfixed is
Asia/Tehran, which schedules clock transitions via the
Iranian calendar, something that even the extended TZ
setting cannot represent.
* localtime.c (getrule): Allow transition times to be signed.
* newtzset.3: Describe the extensions to POSIX TZ strings.
Some of these extensions (e.g., hours == 26) were already
implemented but were not documented. Give examples.
* tzfile.5: Document the relaxed restriction on the stored TZ
string; its hours component can be in the range -167..167 rather
than the POSIX-required 0..24. Refer to newtzset(5).
* zic.c (stringoffset): Allow hours to go up to 167.
(stringrule): Be willing to generate hours in the range -167
through 167.
In several places the code and documentation incorrectly used
"UTC" to describe time stamps that might precede the introduction
of UTC and for which UTC is therefore undefined. Change these
uses to "UT", as that's the correct term when talking about these
time stamps. Problem reported by Steve Allen in
<http://mm.icann.org/pipermail/tz/2013-September/019907.html>.
The major compatibility issue here is with 'zdump -v'; it'll now
output "UT" instead of the possibly-incorrect "UTC".
Many files change in minor ways in the commentary.
* zdump.c (show):
* zic.c (inzsub, addtype):
In output, say "UT" rather than "UTC", since the time stamp we're
talking about might precede the introduction of UTC.