summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--VERSION2
-rw-r--r--WHATSNEW53
-rw-r--r--arch/i386/bits/user.h3
-rw-r--r--arch/m68k/bits/user.h3
-rw-r--r--arch/riscv32/bits/fenv.h5
-rw-r--r--arch/riscv64/bits/fenv.h5
-rw-r--r--src/ctype/iswalnum.c3
-rw-r--r--src/fenv/riscv32/fenv-sf.c2
-rw-r--r--src/fenv/riscv32/fenv.S2
-rw-r--r--src/fenv/riscv64/fenv-sf.c2
-rw-r--r--src/fenv/riscv64/fenv.S2
-rw-r--r--src/locale/gb18030utf.h206
-rw-r--r--src/locale/iconv.c33
-rw-r--r--src/network/res_msend.c2
-rw-r--r--src/regex/regcomp.c6
-rw-r--r--src/stdlib/qsort.c30
-rw-r--r--src/time/__tz.c19
-rw-r--r--src/time/strptime.c13
-rw-r--r--src/time/time_impl.h1
19 files changed, 349 insertions, 43 deletions
diff --git a/VERSION b/VERSION
index c813fe11..3c43790f 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.2.5
+1.2.6
diff --git a/WHATSNEW b/WHATSNEW
index 7bd90728..bb2cd9bd 100644
--- a/WHATSNEW
+++ b/WHATSNEW
@@ -2438,3 +2438,56 @@ arch-specific bugs fixed:
- riscv64 icache flush operation was non-functional
- sh sigsetjmp failed to properly restore call-saved register r8 on return
- sh dlsym RTLD_NEXT did not identify calling module correctly
+
+
+
+1.2.6 release notes
+
+new features:
+- posix_getdents interface (new in POSIX-2024)
+- renameat2 interface (linux extension)
+- iconv support for CP858
+- vdso clock_gettime for riscv{32,64}, powerpc{,64}, and s390x
+- loongarch64 TLSDESC support
+- exposed __getauxval for compiler runtime use detecting cpu features
+
+compatibility:
+- initgroups no longer artificially limits number of supplementary groups
+- getusershell now skips blank lines and comments
+- exit is now explicitly thread-safe (possible future requirement)
+- atexit now fails rather than deadlocking if called from late dtor
+- strerror now has error strings for EUCLEAN and ENAVAIL
+- isatty no longer collapses errors to ENOTTY
+- sched.h namespace pollution with _GNU_SOURCE is reduced
+- hasmntopt now matches only whole options, not arbitrary substrings
+- shadow.h no longer declares an unimplemented sgetspent interface
+- vdso with missing sysv hash table (only gnu hash) is now supported
+
+conformance:
+- pwrite now handles O_APPEND correctly, reports error if it can't
+- mbnrtowcs now conforms to new POSIX-2024 requirement for partial character
+- iconv GBK now properly includes euro symbol
+- strptime now accepts conversion specifiers added in POSIX-2024
+- inet_ntop IPv6 "zero compression" now conforms to RFC 5952
+
+bugs fixed:
+- iconv euc-kr decoder could do oob writes on invalid inputs (CVE-2025-26519)
+- iconv shift_jis decoder could produce wrong outputs for some invalid inputs
+- printf did not honor hex float precision correctly in some cases
+- lost or delayed wakes in sem_post under race condition
+- termios input speed handling was wrong
+- strcasestr failed to match zero-length needle
+- fma handled corner case with negative zero wrongly
+- syslog LOG_MAKEPRI macro was incorrect
+- timer_create is no longer affected by known pthread_barrier bugs
+- sysconf(_SC_MINSIGSTKSZ) computed min size incorrectly
+- statx emulation left some fields uninitialized
+- mntent wrongly included final newline in parsed field output
+- SIGEV_THREAD timers could abort process if SIGTIMER became unblocked
+- bind_textdomain_codeset returned wrong value
+
+arch-specific bugs fixed:
+- early dynamic linker handled page size wrong on dynamic pagesize archs
+- arm and aarch64 crti/n files had wrong alignment
+- m68k POLLWRNORM and POLLWRBAND values were incorrect
+- x32 mq ABI was mismatched
diff --git a/arch/i386/bits/user.h b/arch/i386/bits/user.h
index 33fea986..939db4a2 100644
--- a/arch/i386/bits/user.h
+++ b/arch/i386/bits/user.h
@@ -1,6 +1,3 @@
-#undef __WORDSIZE
-#define __WORDSIZE 32
-
typedef struct user_fpregs_struct {
long cwd, swd, twd, fip, fcs, foo, fos, st_space[20];
} elf_fpregset_t;
diff --git a/arch/m68k/bits/user.h b/arch/m68k/bits/user.h
index 6a443919..2250967b 100644
--- a/arch/m68k/bits/user.h
+++ b/arch/m68k/bits/user.h
@@ -1,6 +1,3 @@
-#undef __WORDSIZE
-#define __WORDSIZE 32
-
struct user_m68kfp_struct {
unsigned long fpregs[24], fpcntl[3];
};
diff --git a/arch/riscv32/bits/fenv.h b/arch/riscv32/bits/fenv.h
index 806ec40f..2c126e6b 100644
--- a/arch/riscv32/bits/fenv.h
+++ b/arch/riscv32/bits/fenv.h
@@ -1,3 +1,7 @@
+#ifdef __riscv_float_abi_soft
+#define FE_ALL_EXCEPT 0
+#define FE_TONEAREST 0
+#else
#define FE_INVALID 16
#define FE_DIVBYZERO 8
#define FE_OVERFLOW 4
@@ -10,6 +14,7 @@
#define FE_DOWNWARD 2
#define FE_UPWARD 3
#define FE_TOWARDZERO 1
+#endif
typedef unsigned int fexcept_t;
typedef unsigned int fenv_t;
diff --git a/arch/riscv64/bits/fenv.h b/arch/riscv64/bits/fenv.h
index 806ec40f..2c126e6b 100644
--- a/arch/riscv64/bits/fenv.h
+++ b/arch/riscv64/bits/fenv.h
@@ -1,3 +1,7 @@
+#ifdef __riscv_float_abi_soft
+#define FE_ALL_EXCEPT 0
+#define FE_TONEAREST 0
+#else
#define FE_INVALID 16
#define FE_DIVBYZERO 8
#define FE_OVERFLOW 4
@@ -10,6 +14,7 @@
#define FE_DOWNWARD 2
#define FE_UPWARD 3
#define FE_TOWARDZERO 1
+#endif
typedef unsigned int fexcept_t;
typedef unsigned int fenv_t;
diff --git a/src/ctype/iswalnum.c b/src/ctype/iswalnum.c
index 046c399c..6e245e85 100644
--- a/src/ctype/iswalnum.c
+++ b/src/ctype/iswalnum.c
@@ -2,7 +2,8 @@
int iswalnum(wint_t wc)
{
- return iswdigit(wc) || iswalpha(wc);
+ if (iswdigit(wc)) return 1;
+ return iswalpha(wc);
}
int __iswalnum_l(wint_t c, locale_t l)
diff --git a/src/fenv/riscv32/fenv-sf.c b/src/fenv/riscv32/fenv-sf.c
index ecd3cb5c..670a77a2 100644
--- a/src/fenv/riscv32/fenv-sf.c
+++ b/src/fenv/riscv32/fenv-sf.c
@@ -1,3 +1,3 @@
-#ifndef __riscv_flen
+#ifdef __riscv_float_abi_soft
#include "../fenv.c"
#endif
diff --git a/src/fenv/riscv32/fenv.S b/src/fenv/riscv32/fenv.S
index 0ea78bf9..1deab07f 100644
--- a/src/fenv/riscv32/fenv.S
+++ b/src/fenv/riscv32/fenv.S
@@ -1,4 +1,4 @@
-#ifdef __riscv_flen
+#ifndef __riscv_float_abi_soft
.global feclearexcept
.type feclearexcept, %function
diff --git a/src/fenv/riscv64/fenv-sf.c b/src/fenv/riscv64/fenv-sf.c
index ecd3cb5c..670a77a2 100644
--- a/src/fenv/riscv64/fenv-sf.c
+++ b/src/fenv/riscv64/fenv-sf.c
@@ -1,3 +1,3 @@
-#ifndef __riscv_flen
+#ifdef __riscv_float_abi_soft
#include "../fenv.c"
#endif
diff --git a/src/fenv/riscv64/fenv.S b/src/fenv/riscv64/fenv.S
index 0ea78bf9..1deab07f 100644
--- a/src/fenv/riscv64/fenv.S
+++ b/src/fenv/riscv64/fenv.S
@@ -1,4 +1,4 @@
-#ifdef __riscv_flen
+#ifndef __riscv_float_abi_soft
.global feclearexcept
.type feclearexcept, %function
diff --git a/src/locale/gb18030utf.h b/src/locale/gb18030utf.h
new file mode 100644
index 00000000..322a2440
--- /dev/null
+++ b/src/locale/gb18030utf.h
@@ -0,0 +1,206 @@
+{ 0x80, 36 },
+{ 0xa5, 2 },
+{ 0xa9, 7 },
+{ 0xb2, 5 },
+{ 0xb8, 31 },
+{ 0xd8, 8 },
+{ 0xe2, 6 },
+{ 0xeb, 1 },
+{ 0xee, 4 },
+{ 0xf4, 3 },
+{ 0xf8, 1 },
+{ 0xfb, 1 },
+{ 0xfd, 4 },
+{ 0x102, 17 },
+{ 0x114, 7 },
+{ 0x11c, 15 },
+{ 0x12c, 24 },
+{ 0x145, 3 },
+{ 0x149, 4 },
+{ 0x14e, 29 },
+{ 0x16c, 98 },
+{ 0x1cf, 1 },
+{ 0x1d1, 1 },
+{ 0x1d3, 1 },
+{ 0x1d5, 1 },
+{ 0x1d7, 1 },
+{ 0x1d9, 1 },
+{ 0x1db, 1 },
+{ 0x1dd, 28 },
+{ 0x1fa, 87 },
+{ 0x252, 15 },
+{ 0x262, 101 },
+{ 0x2c8, 1 },
+{ 0x2cc, 13 },
+{ 0x2da, 183 },
+{ 0x3a2, 1 },
+{ 0x3aa, 7 },
+{ 0x3c2, 1 },
+{ 0x3ca, 55 },
+{ 0x402, 14 },
+{ 0x450, 1 },
+{ 0x452, 7102 },
+{ 0x2011, 2 },
+{ 0x2017, 1 },
+{ 0x201a, 2 },
+{ 0x201e, 7 },
+{ 0x2027, 9 },
+{ 0x2031, 1 },
+{ 0x2034, 1 },
+{ 0x2036, 5 },
+{ 0x203c, 112 },
+{ 0x20ad, 86 },
+{ 0x2104, 1 },
+{ 0x2106, 3 },
+{ 0x210a, 12 },
+{ 0x2117, 10 },
+{ 0x2122, 62 },
+{ 0x216c, 4 },
+{ 0x217a, 22 },
+{ 0x2194, 2 },
+{ 0x219a, 110 },
+{ 0x2209, 6 },
+{ 0x2210, 1 },
+{ 0x2212, 3 },
+{ 0x2216, 4 },
+{ 0x221b, 2 },
+{ 0x2221, 2 },
+{ 0x2224, 1 },
+{ 0x2226, 1 },
+{ 0x222c, 2 },
+{ 0x222f, 5 },
+{ 0x2238, 5 },
+{ 0x223e, 10 },
+{ 0x2249, 3 },
+{ 0x224d, 5 },
+{ 0x2253, 13 },
+{ 0x2262, 2 },
+{ 0x2268, 6 },
+{ 0x2270, 37 },
+{ 0x2296, 3 },
+{ 0x229a, 11 },
+{ 0x22a6, 25 },
+{ 0x22c0, 82 },
+{ 0x2313, 333 },
+{ 0x246a, 10 },
+{ 0x249c, 100 },
+{ 0x254c, 4 },
+{ 0x2574, 13 },
+{ 0x2590, 3 },
+{ 0x2596, 10 },
+{ 0x25a2, 16 },
+{ 0x25b4, 8 },
+{ 0x25be, 8 },
+{ 0x25c8, 3 },
+{ 0x25cc, 2 },
+{ 0x25d0, 18 },
+{ 0x25e6, 31 },
+{ 0x2607, 2 },
+{ 0x260a, 54 },
+{ 0x2641, 1 },
+{ 0x2643, 2110 },
+{ 0x2e82, 2 },
+{ 0x2e85, 3 },
+{ 0x2e89, 2 },
+{ 0x2e8d, 10 },
+{ 0x2e98, 15 },
+{ 0x2ea8, 2 },
+{ 0x2eab, 3 },
+{ 0x2eaf, 4 },
+{ 0x2eb4, 2 },
+{ 0x2eb8, 3 },
+{ 0x2ebc, 14 },
+{ 0x2ecb, 293 },
+{ 0x2ffc, 4 },
+{ 0x3004, 1 },
+{ 0x3018, 5 },
+{ 0x301f, 2 },
+{ 0x302a, 20 },
+{ 0x303f, 2 },
+{ 0x3094, 7 },
+{ 0x309f, 2 },
+{ 0x30f7, 5 },
+{ 0x30ff, 6 },
+{ 0x312a, 246 },
+{ 0x322a, 7 },
+{ 0x3232, 113 },
+{ 0x32a4, 234 },
+{ 0x3390, 12 },
+{ 0x339f, 2 },
+{ 0x33a2, 34 },
+{ 0x33c5, 9 },
+{ 0x33cf, 2 },
+{ 0x33d3, 2 },
+{ 0x33d6, 113 },
+{ 0x3448, 43 },
+{ 0x3474, 298 },
+{ 0x359f, 111 },
+{ 0x360f, 11 },
+{ 0x361b, 765 },
+{ 0x3919, 85 },
+{ 0x396f, 96 },
+{ 0x39d1, 14 },
+{ 0x39e0, 147 },
+{ 0x3a74, 218 },
+{ 0x3b4f, 287 },
+{ 0x3c6f, 113 },
+{ 0x3ce1, 885 },
+{ 0x4057, 264 },
+{ 0x4160, 471 },
+{ 0x4338, 116 },
+{ 0x43ad, 4 },
+{ 0x43b2, 43 },
+{ 0x43de, 248 },
+{ 0x44d7, 373 },
+{ 0x464d, 20 },
+{ 0x4662, 193 },
+{ 0x4724, 5 },
+{ 0x472a, 82 },
+{ 0x477d, 16 },
+{ 0x478e, 441 },
+{ 0x4948, 50 },
+{ 0x497b, 2 },
+{ 0x497e, 4 },
+{ 0x4984, 1 },
+{ 0x4987, 20 },
+{ 0x499c, 3 },
+{ 0x49a0, 22 },
+{ 0x49b8, 703 },
+{ 0x4c78, 39 },
+{ 0x4ca4, 111 },
+{ 0x4d1a, 148 },
+{ 0x4daf, 81 },
+{ 0x9fa6, 14426 },
+{ 0xe76c, 1 },
+{ 0xe7c8, 1 },
+{ 0xe7e7, 13 },
+{ 0xe815, 1 },
+{ 0xe819, 5 },
+{ 0xe81f, 7 },
+{ 0xe827, 4 },
+{ 0xe82d, 4 },
+{ 0xe833, 8 },
+{ 0xe83c, 7 },
+{ 0xe844, 16 },
+{ 0xe856, 14 },
+{ 0xe865, 4295 },
+{ 0xf92d, 76 },
+{ 0xf97a, 27 },
+{ 0xf996, 81 },
+{ 0xf9e8, 9 },
+{ 0xf9f2, 26 },
+{ 0xfa10, 1 },
+{ 0xfa12, 1 },
+{ 0xfa15, 3 },
+{ 0xfa19, 6 },
+{ 0xfa22, 1 },
+{ 0xfa25, 2 },
+{ 0xfa2a, 1030 },
+{ 0xfe32, 1 },
+{ 0xfe45, 4 },
+{ 0xfe53, 1 },
+{ 0xfe58, 1 },
+{ 0xfe67, 1 },
+{ 0xfe6c, 149 },
+{ 0xff5f, 129 },
+{ 0xffe6, 26 },
diff --git a/src/locale/iconv.c b/src/locale/iconv.c
index 52178950..4151411d 100644
--- a/src/locale/iconv.c
+++ b/src/locale/iconv.c
@@ -74,6 +74,10 @@ static const unsigned short gb18030[126][190] = {
#include "gb18030.h"
};
+static const unsigned short gb18030utf[][2] = {
+#include "gb18030utf.h"
+};
+
static const unsigned short big5[89][157] = {
#include "big5.h"
};
@@ -224,6 +228,8 @@ static unsigned uni_to_jis(unsigned c)
}
}
+#define countof(a) (sizeof (a) / sizeof *(a))
+
size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restrict out, size_t *restrict outb)
{
size_t x=0;
@@ -430,15 +436,24 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
d = *((unsigned char *)*in + 3);
if (d-'0'>9) goto ilseq;
c += d-'0';
- c += 128;
- for (d=0; d<=c; ) {
- k = 0;
- for (int i=0; i<126; i++)
- for (int j=0; j<190; j++)
- if (gb18030[i][j]-d <= c-d)
- k++;
- d = c+1;
- c += k;
+ /* Starting at 90 30 81 30 (189000), mapping is
+ * linear without gaps, to U+10000 and up. */
+ if (c >= 189000) {
+ c -= 189000;
+ c += 0x10000;
+ if (c >= 0x110000) goto ilseq;
+ break;
+ }
+ /* Otherwise we must process an index into set
+ * of characters unmapped by 2-byte table. */
+ for (int i=0; ; i++) {
+ if (i==countof(gb18030utf))
+ goto ilseq;
+ if (c<gb18030utf[i][1]) {
+ c += gb18030utf[i][0];
+ break;
+ }
+ c -= gb18030utf[i][1];
}
break;
}
diff --git a/src/network/res_msend.c b/src/network/res_msend.c
index fcb52513..51d42ecb 100644
--- a/src/network/res_msend.c
+++ b/src/network/res_msend.c
@@ -124,7 +124,7 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries,
/* Handle case where system lacks IPv6 support */
if (fd < 0 && family == AF_INET6 && errno == EAFNOSUPPORT) {
- for (i=0; i<nns && conf->ns[nns].family == AF_INET6; i++);
+ for (i=0; i<nns && conf->ns[i].family == AF_INET6; i++);
if (i==nns) {
pthread_setcancelstate(cs, 0);
return -1;
diff --git a/src/regex/regcomp.c b/src/regex/regcomp.c
index fb24556e..b4b81968 100644
--- a/src/regex/regcomp.c
+++ b/src/regex/regcomp.c
@@ -409,6 +409,8 @@ typedef struct {
int position;
/* The highest back reference or -1 if none seen so far. */
int max_backref;
+ /* Bit mask of submatch IDs that can be back referenced. */
+ int backref_ok;
/* Compilation flags. */
int cflags;
} tre_parse_ctx_t;
@@ -769,6 +771,8 @@ static reg_errcode_t marksub(tre_parse_ctx_t *ctx, tre_ast_node_t *node, int sub
node->submatch_id = subid;
node->num_submatches++;
ctx->n = node;
+ if (subid < 10)
+ ctx->backref_ok |= 1<<subid;
return REG_OK;
}
@@ -864,6 +868,8 @@ static reg_errcode_t parse_atom(tre_parse_ctx_t *ctx, const char *s)
if (!ere && (unsigned)*s-'1' < 9) {
/* back reference */
int val = *s - '0';
+ if (!(ctx->backref_ok & 1<<val))
+ return REG_ESUBREG;
node = tre_ast_new_literal(ctx->mem, BACKREF, val, ctx->position++);
ctx->max_backref = MAX(val, ctx->max_backref);
} else {
diff --git a/src/stdlib/qsort.c b/src/stdlib/qsort.c
index ab79dc6f..28607450 100644
--- a/src/stdlib/qsort.c
+++ b/src/stdlib/qsort.c
@@ -34,11 +34,11 @@
typedef int (*cmpfun)(const void *, const void *, void *);
+/* returns index of first bit set, excluding the low bit assumed to always
+ * be set, starting from low bit of p[0] up through high bit of p[1] */
static inline int pntz(size_t p[2]) {
- int r = ntz(p[0] - 1);
- if(r != 0 || (r = 8*sizeof(size_t) + ntz(p[1])) != 8*sizeof(size_t)) {
- return r;
- }
+ if (p[0] != 1) return ntz(p[0] - 1);
+ if (p[1]) return 8*sizeof(size_t) + ntz(p[1]);
return 0;
}
@@ -71,6 +71,7 @@ static inline void shl(size_t p[2], int n)
n -= 8 * sizeof(size_t);
p[1] = p[0];
p[0] = 0;
+ if (!n) return;
}
p[1] <<= n;
p[1] |= p[0] >> (sizeof(size_t) * 8 - n);
@@ -83,16 +84,23 @@ static inline void shr(size_t p[2], int n)
n -= 8 * sizeof(size_t);
p[0] = p[1];
p[1] = 0;
+ if (!n) return;
}
p[0] >>= n;
p[0] |= p[1] << (sizeof(size_t) * 8 - n);
p[1] >>= n;
}
+/* power-of-two length for working array so that we can mask indices and
+ * not depend on any invariant of the algorithm for spatial memory safety.
+ * the original size was just 14*sizeof(size_t)+1 */
+#define AR_LEN (16 * sizeof(size_t))
+#define AR_MASK (AR_LEN - 1)
+
static void sift(unsigned char *head, size_t width, cmpfun cmp, void *arg, int pshift, size_t lp[])
{
unsigned char *rt, *lf;
- unsigned char *ar[14 * sizeof(size_t) + 1];
+ unsigned char *ar[AR_LEN];
int i = 1;
ar[0] = head;
@@ -104,16 +112,16 @@ static void sift(unsigned char *head, size_t width, cmpfun cmp, void *arg, int p
break;
}
if(cmp(lf, rt, arg) >= 0) {
- ar[i++] = lf;
+ ar[i++ & AR_MASK] = lf;
head = lf;
pshift -= 1;
} else {
- ar[i++] = rt;
+ ar[i++ & AR_MASK] = rt;
head = rt;
pshift -= 2;
}
}
- cycle(width, ar, i);
+ cycle(width, ar, i & AR_MASK);
}
static void trinkle(unsigned char *head, size_t width, cmpfun cmp, void *arg, size_t pp[2], int pshift, int trusty, size_t lp[])
@@ -121,7 +129,7 @@ static void trinkle(unsigned char *head, size_t width, cmpfun cmp, void *arg, si
unsigned char *stepson,
*rt, *lf;
size_t p[2];
- unsigned char *ar[14 * sizeof(size_t) + 1];
+ unsigned char *ar[AR_LEN];
int i = 1;
int trail;
@@ -142,7 +150,7 @@ static void trinkle(unsigned char *head, size_t width, cmpfun cmp, void *arg, si
}
}
- ar[i++] = stepson;
+ ar[i++ & AR_MASK] = stepson;
head = stepson;
trail = pntz(p);
shr(p, trail);
@@ -150,7 +158,7 @@ static void trinkle(unsigned char *head, size_t width, cmpfun cmp, void *arg, si
trusty = 0;
}
if(!trusty) {
- cycle(width, ar, i);
+ cycle(width, ar, i & AR_MASK);
sift(head, width, cmp, arg, pshift, lp);
}
}
diff --git a/src/time/__tz.c b/src/time/__tz.c
index 54ed4cf6..cfce268e 100644
--- a/src/time/__tz.c
+++ b/src/time/__tz.c
@@ -436,3 +436,22 @@ const char *__tm_to_tzname(const struct tm *tm)
UNLOCK(lock);
return p;
}
+
+int __tzname_to_isdst(const char *restrict *s)
+{
+ size_t len;
+ int isdst = -1;
+ LOCK(lock);
+ if (tzname[0] && !strncmp(*s, tzname[0], len = strlen(tzname[0]))) {
+ isdst = 0;
+ *s += len;
+ } else if (tzname[1] && !strncmp(*s, tzname[1], len=strlen(tzname[1]))) {
+ isdst = 1;
+ *s += len;
+ } else {
+ /* FIXME: is this supposed to be an error? */
+ while (isalpha(**s)) ++*s;
+ }
+ UNLOCK(lock);
+ return isdst;
+}
diff --git a/src/time/strptime.c b/src/time/strptime.c
index b1147242..40bb37af 100644
--- a/src/time/strptime.c
+++ b/src/time/strptime.c
@@ -5,6 +5,7 @@
#include <stddef.h>
#include <string.h>
#include <strings.h>
+#include "time_impl.h"
char *strptime(const char *restrict s, const char *restrict f, struct tm *restrict tm)
{
@@ -207,16 +208,8 @@ char *strptime(const char *restrict s, const char *restrict f, struct tm *restri
s += 5;
break;
case 'Z':
- if (!strncmp(s, tzname[0], len = strlen(tzname[0]))) {
- tm->tm_isdst = 0;
- s += len;
- } else if (!strncmp(s, tzname[1], len=strlen(tzname[1]))) {
- tm->tm_isdst = 1;
- s += len;
- } else {
- /* FIXME: is this supposed to be an error? */
- while ((*s|32)-'a' <= 'z'-'a') s++;
- }
+ i = __tzname_to_isdst(&s);
+ if (i>=0) tm->tm_isdst = i;
break;
case '%':
if (*s++ != '%') return 0;
diff --git a/src/time/time_impl.h b/src/time/time_impl.h
index f26d8005..ffe5050b 100644
--- a/src/time/time_impl.h
+++ b/src/time/time_impl.h
@@ -5,6 +5,7 @@ hidden int __month_to_secs(int, int);
hidden long long __year_to_secs(long long, int *);
hidden long long __tm_to_secs(const struct tm *);
hidden const char *__tm_to_tzname(const struct tm *);
+hidden int __tzname_to_isdst(const char *restrict *);
hidden int __secs_to_tm(long long, struct tm *);
hidden void __secs_to_zone(long long, int, int *, long *, long *, const char **);
hidden const char *__strftime_fmt_1(char (*)[100], size_t *, int, const struct tm *, locale_t, int);