Age | Commit message (Collapse) | Author | Files | Lines |
|
|
|
previously, setting TZ to the pathname of a file which was not a valid
zoneinfo file would usually cause programs using local time zone based
operations to crash. the new code checks the file size and magic at
the beginning of the file, which seems sufficient to prevent
accidental misconfiguration from causing crashes. attempting to make
fully-robust validation would be futile unless we wanted to drop use
of mmap (shared zoneinfo) and instead read it into a local buffer,
since such validation would be subject to race conditions with
modification of the file.
|
|
|
|
since the form TZ=name is reserved for POSIX-form time zone strings,
TZ=:name needs to be used when the zoneinfo filename is in the
top-level zoneinfo directory and therefore does not contain a slash.
previously the leading colon was merely dropped, making it impossible
to access such zones without a full absolute pathname.
changes based on patch by Timo Teräs.
|
|
the vdso symbol lookup code is based on the original 2011 patch by
Nicholas J. Kain, with some streamlining, pointer arithmetic fixes,
and one symbol version matching fix.
on the consumer side (clock_gettime), per-arch macros for the
particular symbol name and version to lookup are added in
syscall_arch.h, and no vdso code is pulled in on archs which do not
define these macros. at this time, vdso is enabled only on x86_64.
the vdso support at the dynamic linker level is no longer useful to
libc, but is left in place for the sake of debuggers (which may need
the vdso in the link map to find its functions) and possibly use with
dlsym.
|
|
|
|
this practice came from very early, before internal/syscall.h defined
macros that could accept pointer arguments directly and handle them
correctly. aside from being ugly and unnecessary, it looks like it
will be problematic when we add support for 32-bit ABIs on archs where
registers (and syscall arguments) are 64-bit, e.g. x32 and mips n32.
|
|
|
|
|
|
these functions were spuriously failing in the case where the buffer
size was exactly the number of bytes/characters to be written,
including null termination. since these functions do not have defined
error conditions other than buffer size, a reasonable application may
fail to check the return value when the format string and buffer size
are known to be valid; such an application could then attempt to use a
non-terminated buffer.
in addition to fixing the bug, I have changed the error handling
behavior so that these functions always null-terminate the output
except in the case where the buffer size is zero, and so that they
always write as many characters as possible before failing, rather
than dropping whole fields that do not fit. this actually simplifies
the logic somewhat anyway.
|
|
it's not clear why I originally wrote O_NOFOLLOW into this; I suspect
the reason was with an aim of making the function more general for
mapping partially or fully untrusted files provided by the user.
however, the timezone code already precludes use of absolute or
relative pathnames in suid/sgid programs, and disallows .. in
pathnames which are relative to one of the system timezone locations,
so there is no threat of opening a symlink which is not trusted by
appropriate user. since some users may wish to put symbolic links in
the zoneinfo directories to alias timezones, it seems preferable to
allow this.
|
|
the rest of the code is not prepared to handle an empty TZ string, so
falling back to __gmt ("GMT"), just as if TZ had been blank or unset,
is the preferable action.
|
|
try+l points to \0, so only one iteration was ever tried.
|
|
we need to skip to the second TZif header, which starts at
skip+44, and then skip another header (20 bytes) plus the following
6 32bit values.
|
|
if sizeof(time_t) == 8, this code path was missing the correct
offset into the zoneinfo file, using the header magic to do
offset calculations.
the 6 32bit fields to be read start at offset 20.
|
|
despite being marked legacy, this was specified by SUSv3 as part of
the XSI option; only the most recent version of the standard dropped
it. reportedly there's actual code using it.
|
|
this is a nonstandard extension but will be required in the next
version of POSIX, and it's widely used/useful in shell scripts
utilizing the date utility.
|
|
%e pads with spaces instead of zeros.
|
|
in this case, the first standard-time and first daylight-time rules
should be taken as the "default" ones to expose.
|
|
if a zoneinfo file is not (or is no longer) in use, don't check the
abbrevs pointers, which may be invalid.
|
|
this may need further revision in the future, since POSIX is rather
unclear on the requirements, and is designed around the assumption of
POSIX TZ specifiers which are not sufficiently powerful to represent
real-world timezones (this is why zoneinfo support was added).
the basic issue is that strftime gets the string and numeric offset
for the timezone from the extra fields in struct tm, which are
initialized when calling localtime/gmtime/etc. however, a conforming
application might have created its own struct tm without initializing
these fields, in which case using __tm_zone (a pointer) could crash.
other zoneinfo-based implementations simply check for a null pointer,
but otherwise can still crash of the field contains junk.
simply ignoring __tm_zone and using tzname[] would "work" but would
give incorrect results in time zones with more complex rules. I feel
like this would lower the quality of implementation.
instead, simply validate __tm_zone: unless it points to one of the
zone name strings managed by the timezone system, assume it's invalid.
this commit also fixes several other minor bugs with formatting:
tm_isdst being negative is required to suppress printing of the zone
formats, and %z was using the wrong format specifiers since the type
of val was changed, resulting in bogus output.
|
|
the empty TZ string was matching equal to the initial value of the
cached TZ name, thus causing do_tzset never to run and never to
initialize the time zone data.
|
|
this bug was masked by local experimental CFLAGS in my config.mak.
|
|
at present, since POSIX requires %F to behave as %+4Y-%m-%d and ISO C
requires %F to behave as %Y-%m-%d, the default behavior for %Y has
been changed to match %+4Y. this seems to be the only way to conform
to the requirements of both standards, and it does not affect years
prior to the year 10000. depending on the outcome of interpretations
from the standards bodies, this may be adjusted at some point.
|
|
use a long long value so that even with offsets, values cannot
overflow. instead of using different format strings for different
numeric formats, simply use a per-format width and %0*lld for all of
them.
this width specifier is not for use with strftime field widths; that
will be a separate step in the caller.
|
|
|
|
make __strftime_fmt_1 return a string (possibly in the caller-provided
temp buffer) rather than writing into the output buffer. this approach
makes more sense when padding to a minimum field width might be
required, and it's also closer to what wcsftime wants.
|
|
|
|
unblocking it in the pthread_once init function is not sufficient,
since multiple threads, some of them with the signal blocked, could
already exist before this is called; timers started from such threads
would be non-functional.
|
|
this is needed for reused threads in the SIGEV_THREAD timer
notification system, and could be reused elsewhere in the future if
needed, though it should be refactored for such use.
for static linking, __init_tls.c is simply modified to export the TLS
info in a structure with external linkage, rather than using statics.
this perhaps makes the code more clear, since the statics were poorly
named for statics. the new __reset_tls.c is only linked if it is used.
for dynamic linking, the code is in dynlink.c. sharing code with
__copy_tls is not practical since __reset_tls must also re-zero
thread-local bss.
|
|
1. the thread result field was reused for storing a kernel timer id,
but would be overwritten if the application code exited or cancelled
the thread.
2. low pointer values were used as the indicator that the timer id is
a kernel timer id rather than a thread id. this is not portable, as
mmap may return low pointers on some conditions. instead, use the fact
that pointers must be aligned and kernel timer ids must be
non-negative to map pointers into the negative integer space.
3. signals were not blocked until after the timer thread started, so a
race condition could allow a signal handler to run in the timer thread
when it's not supposed to exist. this is mainly problematic if the
calling thread was the only thread where the signal was unblocked and
the signal handler assumes it runs in that thread.
|
|
this is a nonstandard extension.
|
|
LC_GLOBAL_LOCALE refers to the global locale, controlled by setlocale,
not the thread-local locale in effect which these functions should be
using. neither LC_GLOBAL_LOCALE nor 0 has an argument to the *_l
functions has behavior defined by the standard, but 0 is a more
logical choice for requesting the callee to lookup the current locale.
in the future I may move the current locale lookup the the caller (the
non-_l-suffixed wrapper).
at this point, all of the locale logic is dummied out, so no harm was
done, but it should at least avoid misleading usage.
|
|
this change is in preparation for possibly adding support for the
field width and padding specifiers added in POSIX 2008.
|
|
|
|
unlike the strftime commit, this one is purely an ABI compatibility
issue. the previous version of the code would have worked just as well
with LC_TIME once LC_TIME support is added.
|
|
the latter is both for ABI purposes, and to facilitate eventually
adding LC_TIME support. it's also nice to eliminate an extra source
file.
|
|
POSIX mandates EOVERFLOW for this condition.
|
|
|
|
this commit has two major user-visible parts: zoneinfo-format time
zones are now supported, and overflow handling is intended to be
complete in the sense that all functions return a correct result if
and only if the result fits in the destination type, and otherwise
return an error. also, some noticable bugs in the way DST detection
and normalization worked have been fixed, and performance may be
better than before, but it has not been tested.
|
|
in the process, I refactored the week-number code so it can be used by
the week-based-year formats to determine year adjustments at the
boundary values. this also improves indention/code readability.
|
|
that's what I get for changing a hard-coded threshold to a proper
non-magic-number without testing.
|
|
output for plain week numbers (%U and %W) has been sanity-checked, and
output for the week-based-year week numbers (%V) has been checked
extensively against known-good data for the full non-negative range of
32-bit time_t.
year numbers for week-based years (%g and %G) are not yet implemented.
|
|
apparently these features have been in Linux for a while now, so it
makes sense to support them. the bit twiddling seems utterly illogical
and wasteful, especially the negation, but that's how the kernel folks
chose to encode pids/tids into the clock id.
|
|
per Austin Group interpretation for issue #686, which cites the
requirements of ISO C, clock() cannot wrap. if the result is not
representable, it must return (clock_t)-1. in addition, the old code
was performing wrapping via signed overflow and thus invoking
undefined behavior.
since it seems impossible to accurately check for overflow with the
old times()-based fallback code, I have simply dropped the fallback
code for now, thus always returning -1 on ancient systems. if there's
a demand for making it work and somebody comes up with a way, it could
be reinstated, but the clock() function is essentially useless on
32-bit system anyway (it overflows in less than an hour).
it should be noted that I used LONG_MAX rather than ULONG_MAX, despite
32-bit archs using an unsigned type for clock_t. this discrepency with
the glibc/LSB type definitions will be fixed now; since wrapping of
clock_t is no longer supported, there's no use in it being unsigned.
|
|
since CLOCKS_PER_SEC is 1000000 (required by XSI) and the times
syscall reports values in 1/100 second units (Linux), the correct
scaling factor is 10000, not 100. note that only ancient kernels which
lack clock_gettime are affected.
|
|
all return values are valid, and on 32-bit systems, values that look
like errors can and will occur. since the only actual error this
function could return is EFAULT, and it is only returnable when the
application has invoked undefined behavior, simply ignore the
possibility that the return value is actually an error code.
|
|
|
|
|
|
the issue at hand is that many syscalls require as an argument the
kernel-ABI size of sigset_t, intended to allow the kernel to switch to
a larger sigset_t in the future. previously, each arch was defining
this size in syscall_arch.h, which was redundant with the definition
of _NSIG in bits/signal.h. as it's used in some not-quite-portable
application code as well, _NSIG is much more likely to be recognized
and understood immediately by someone reading the code, and it's also
shorter and less cluttered.
note that _NSIG is actually 65/129, not 64/128, but the division takes
care of throwing away the off-by-one part.
|