diff options
Diffstat (limited to 'src')
76 files changed, 820 insertions, 250 deletions
diff --git a/src/complex/cacosh.c b/src/complex/cacosh.c index 76127f75..55b857ce 100644 --- a/src/complex/cacosh.c +++ b/src/complex/cacosh.c @@ -1,6 +1,6 @@ #include "complex_impl.h" -/* acosh(z) = i acos(z) */ +/* acosh(z) = ±i acos(z) */ double complex cacosh(double complex z) { diff --git a/src/complex/catan.c b/src/complex/catan.c index ccc2fb53..b4fe552a 100644 --- a/src/complex/catan.c +++ b/src/complex/catan.c @@ -60,29 +60,6 @@ #include "complex_impl.h" -#define MAXNUM 1.0e308 - -static const double DP1 = 3.14159265160560607910E0; -static const double DP2 = 1.98418714791870343106E-9; -static const double DP3 = 1.14423774522196636802E-17; - -static double _redupi(double x) -{ - double t; - long i; - - t = x/M_PI; - if (t >= 0.0) - t += 0.5; - else - t -= 0.5; - - i = t; /* the multiple */ - t = i; - t = ((x - t * DP1) - t * DP2) - t * DP3; - return t; -} - double complex catan(double complex z) { double complex w; @@ -95,7 +72,7 @@ double complex catan(double complex z) a = 1.0 - x2 - (y * y); t = 0.5 * atan2(2.0 * x, a); - w = _redupi(t); + w = t; t = y - 1.0; a = x2 + (t * t); diff --git a/src/complex/catanf.c b/src/complex/catanf.c index 1d569f2d..faaa907a 100644 --- a/src/complex/catanf.c +++ b/src/complex/catanf.c @@ -55,32 +55,6 @@ #include "complex_impl.h" -#define MAXNUMF 1.0e38F - -static const double DP1 = 3.140625; -static const double DP2 = 9.67502593994140625E-4; -static const double DP3 = 1.509957990978376432E-7; - -static const float float_pi = M_PI; - -static float _redupif(float xx) -{ - float x, t; - long i; - - x = xx; - t = x/float_pi; - if (t >= 0.0f) - t += 0.5f; - else - t -= 0.5f; - - i = t; /* the multiple */ - t = i; - t = ((x - t * DP1) - t * DP2) - t * DP3; - return t; -} - float complex catanf(float complex z) { float complex w; @@ -93,7 +67,7 @@ float complex catanf(float complex z) a = 1.0f - x2 - (y * y); t = 0.5f * atan2f(2.0f * x, a); - w = _redupif(t); + w = t; t = y - 1.0f; a = x2 + (t * t); diff --git a/src/complex/catanl.c b/src/complex/catanl.c index e62526c0..cd2d2b00 100644 --- a/src/complex/catanl.c +++ b/src/complex/catanl.c @@ -67,28 +67,6 @@ long double complex catanl(long double complex z) return catan(z); } #else -static const long double PIL = 3.141592653589793238462643383279502884197169L; -static const long double DP1 = 3.14159265358979323829596852490908531763125L; -static const long double DP2 = 1.6667485837041756656403424829301998703007e-19L; -static const long double DP3 = 1.8830410776607851167459095484560349402753e-39L; - -static long double redupil(long double x) -{ - long double t; - long i; - - t = x / PIL; - if (t >= 0.0L) - t += 0.5L; - else - t -= 0.5L; - - i = t; /* the multiple */ - t = i; - t = ((x - t * DP1) - t * DP2) - t * DP3; - return t; -} - long double complex catanl(long double complex z) { long double complex w; @@ -101,7 +79,7 @@ long double complex catanl(long double complex z) a = 1.0L - x2 - (y * y); t = atan2l(2.0L * x, a) * 0.5L; - w = redupil(t); + w = t; t = y - 1.0L; a = x2 + (t * t); diff --git a/src/conf/sysconf.c b/src/conf/sysconf.c index 60d3e745..8dd5c725 100644 --- a/src/conf/sysconf.c +++ b/src/conf/sysconf.c @@ -220,8 +220,13 @@ long sysconf(int name) return (mem > LONG_MAX) ? LONG_MAX : mem; case JT_MINSIGSTKSZ & 255: case JT_SIGSTKSZ & 255: ; - long val = __getauxval(AT_MINSIGSTKSZ); - if (val < MINSIGSTKSZ) val = MINSIGSTKSZ; + /* Value from auxv/kernel is only sigfame size. Clamp it + * to at least 1k below arch's traditional MINSIGSTKSZ, + * then add 1k of working space for signal handler. */ + unsigned long sigframe_sz = __getauxval(AT_MINSIGSTKSZ); + if (sigframe_sz < MINSIGSTKSZ - 1024) + sigframe_sz = MINSIGSTKSZ - 1024; + unsigned val = sigframe_sz + 1024; if (values[name] == JT_SIGSTKSZ) val += SIGSTKSZ - MINSIGSTKSZ; return val; 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/dirent/posix_getdents.c b/src/dirent/posix_getdents.c new file mode 100644 index 00000000..26c16ac6 --- /dev/null +++ b/src/dirent/posix_getdents.c @@ -0,0 +1,11 @@ +#include <dirent.h> +#include <limits.h> +#include <errno.h> +#include "syscall.h" + +ssize_t posix_getdents(int fd, void *buf, size_t len, int flags) +{ + if (flags) return __syscall_ret(-EOPNOTSUPP); + if (len>INT_MAX) len = INT_MAX; + return syscall(SYS_getdents, fd, buf, len); +} diff --git a/src/errno/__strerror.h b/src/errno/__strerror.h index 14925907..0398b5b6 100644 --- a/src/errno/__strerror.h +++ b/src/errno/__strerror.h @@ -97,6 +97,8 @@ E(ESHUTDOWN, "Cannot send after socket shutdown") E(EALREADY, "Operation already in progress") E(EINPROGRESS, "Operation in progress") E(ESTALE, "Stale file handle") +E(EUCLEAN, "Data consistency error") +E(ENAVAIL, "Resource not available") E(EREMOTEIO, "Remote I/O error") E(EDQUOT, "Quota exceeded") E(ENOMEDIUM, "No medium found") diff --git a/src/exit/atexit.c b/src/exit/atexit.c index 854e9fdd..92c91c9d 100644 --- a/src/exit/atexit.c +++ b/src/exit/atexit.c @@ -19,6 +19,7 @@ static struct fl void *a[COUNT]; } builtin, *head; +static int finished_atexit; static int slot; static volatile int lock[1]; volatile int *const __atexit_lockptr = lock; @@ -34,6 +35,10 @@ void __funcs_on_exit() func(arg); LOCK(lock); } + /* Unlock to prevent deadlock if a global dtor + * attempts to call atexit. */ + finished_atexit = 1; + UNLOCK(lock); } void __cxa_finalize(void *dso) @@ -44,6 +49,13 @@ int __cxa_atexit(void (*func)(void *), void *arg, void *dso) { LOCK(lock); + /* Prevent dtors from registering further atexit + * handlers that would never be run. */ + if (finished_atexit) { + UNLOCK(lock); + return -1; + } + /* Defer initialization of head so it can be in BSS */ if (!head) head = &builtin; diff --git a/src/exit/exit.c b/src/exit/exit.c index a6869b37..17b33cc6 100644 --- a/src/exit/exit.c +++ b/src/exit/exit.c @@ -1,6 +1,9 @@ #include <stdlib.h> #include <stdint.h> #include "libc.h" +#include "pthread_impl.h" +#include "atomic.h" +#include "syscall.h" static void dummy() { @@ -26,6 +29,17 @@ weak_alias(libc_exit_fini, __libc_exit_fini); _Noreturn void exit(int code) { + /* Handle potentially concurrent or recursive calls to exit, + * whose behaviors have traditionally been undefined by the + * standards. Using a custom lock here avoids pulling in lock + * machinery and lets us trap recursive calls while supporting + * multiple threads contending to be the one to exit(). */ + static volatile int exit_lock[1]; + int tid = __pthread_self()->tid; + int prev = a_cas(exit_lock, 0, tid); + if (prev == tid) a_crash(); + else if (prev) for (;;) __sys_pause(); + __funcs_on_exit(); __libc_exit_fini(); __stdio_exit(); diff --git a/src/fenv/loongarch64/fenv-sf.c b/src/fenv/loongarch64/fenv-sf.c new file mode 100644 index 00000000..41154673 --- /dev/null +++ b/src/fenv/loongarch64/fenv-sf.c @@ -0,0 +1,3 @@ +#ifdef __loongarch_soft_float +#include "../fenv.c" +#endif 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/include/sys/auxv.h b/src/include/sys/auxv.h index 9358a4a5..63c5bfe9 100644 --- a/src/include/sys/auxv.h +++ b/src/include/sys/auxv.h @@ -5,6 +5,6 @@ #include <features.h> -hidden unsigned long __getauxval(unsigned long); +unsigned long __getauxval(unsigned long); #endif diff --git a/src/internal/syscall.h b/src/internal/syscall.h index 33d981f9..2d8a5c13 100644 --- a/src/internal/syscall.h +++ b/src/internal/syscall.h @@ -391,6 +391,17 @@ static inline long __alt_socketcall(int sys, int sock, int cp, syscall_arg_t a, #define __sys_open_cp(...) __SYSCALL_DISP(__sys_open_cp,,__VA_ARGS__) #define sys_open_cp(...) __syscall_ret(__sys_open_cp(__VA_ARGS__)) +#ifdef SYS_pause +#define __sys_pause() __syscall(SYS_pause) +#define __sys_pause_cp() __syscall_cp(SYS_pause) +#else +#define __sys_pause() __syscall(SYS_ppoll, 0, 0, 0, 0) +#define __sys_pause_cp() __syscall_cp(SYS_ppoll, 0, 0, 0, 0) +#endif + +#define sys_pause() __syscall_ret(__sys_pause()) +#define sys_pause_cp() __syscall_ret(__sys_pause_cp()) + #ifdef SYS_wait4 #define __sys_wait4(a,b,c,d) __syscall(SYS_wait4,a,b,c,d) #define __sys_wait4_cp(a,b,c,d) __syscall_cp(SYS_wait4,a,b,c,d) diff --git a/src/internal/vdso.c b/src/internal/vdso.c index d46d3228..2b6e1ae2 100644 --- a/src/internal/vdso.c +++ b/src/internal/vdso.c @@ -40,6 +40,24 @@ static int checkver(Verdef *def, int vsym, const char *vername, char *strings) #define OK_TYPES (1<<STT_NOTYPE | 1<<STT_OBJECT | 1<<STT_FUNC | 1<<STT_COMMON) #define OK_BINDS (1<<STB_GLOBAL | 1<<STB_WEAK | 1<<STB_GNU_UNIQUE) +static size_t count_syms_gnu(uint32_t *gh) +{ + size_t nsym, i; + uint32_t *buckets = gh + 4 + (gh[2]*sizeof(size_t)/4); + uint32_t *hashval; + for (i = nsym = 0; i < gh[0]; i++) { + if (buckets[i] > nsym) + nsym = buckets[i]; + } + if (nsym) { + hashval = buckets + gh[0] + (nsym - gh[1]); + do nsym++; + while (!(*hashval++ & 1)); + } + return nsym; +} + + void *__vdsosym(const char *vername, const char *name) { size_t i; @@ -60,6 +78,7 @@ void *__vdsosym(const char *vername, const char *name) char *strings = 0; Sym *syms = 0; Elf_Symndx *hashtab = 0; + uint32_t *ghashtab = 0; uint16_t *versym = 0; Verdef *verdef = 0; @@ -69,15 +88,20 @@ void *__vdsosym(const char *vername, const char *name) case DT_STRTAB: strings = p; break; case DT_SYMTAB: syms = p; break; case DT_HASH: hashtab = p; break; + case DT_GNU_HASH: ghashtab = p; break; case DT_VERSYM: versym = p; break; case DT_VERDEF: verdef = p; break; } } - if (!strings || !syms || !hashtab) return 0; + if (!strings || !syms) return 0; if (!verdef) versym = 0; + size_t nsym = 0; + + if (hashtab) nsym = hashtab[1]; + else if (ghashtab) nsym = count_syms_gnu(ghashtab); - for (i=0; i<hashtab[1]; i++) { + for (i=0; i<nsym; i++) { if (!(1<<(syms[i].st_info&0xf) & OK_TYPES)) continue; if (!(1<<(syms[i].st_info>>4) & OK_BINDS)) continue; if (!syms[i].st_shndx) continue; diff --git a/src/ldso/loongarch64/tlsdesc.s b/src/ldso/loongarch64/tlsdesc.s new file mode 100644 index 00000000..4b6ea0e5 --- /dev/null +++ b/src/ldso/loongarch64/tlsdesc.s @@ -0,0 +1,37 @@ +.text +.global __tlsdesc_static +.hidden __tlsdesc_static +.type __tlsdesc_static,%function +__tlsdesc_static: + ld.d $a0, $a0, 8 + jr $ra +# size_t __tlsdesc_dynamic(size_t *a) +# { +# struct {size_t modidx,off;} *p = (void*)a[1]; +# size_t *dtv = *(size_t**)(tp - 8); +# return dtv[p->modidx] + p->off - tp; +# } +.global __tlsdesc_dynamic +.hidden __tlsdesc_dynamic +.type __tlsdesc_dynamic,%function +__tlsdesc_dynamic: + addi.d $sp, $sp, -16 + st.d $t1, $sp, 0 + st.d $t2, $sp, 8 + + ld.d $t2, $tp, -8 # t2=dtv + + ld.d $a0, $a0, 8 # a0=&{modidx,off} + ld.d $t1, $a0, 8 # t1=off + ld.d $a0, $a0, 0 # a0=modidx + slli.d $a0, $a0, 3 # a0=8*modidx + + add.d $a0, $a0, $t2 # a0=dtv+8*modidx + ld.d $a0, $a0, 0 # a0=dtv[modidx] + add.d $a0, $a0, $t1 # a0=dtv[modidx]+off + sub.d $a0, $a0, $tp # a0=dtv[modidx]+off-tp + + ld.d $t1, $sp, 0 + ld.d $t2, $sp, 8 + addi.d $sp, $sp, 16 + jr $ra diff --git a/src/legacy/getusershell.c b/src/legacy/getusershell.c index 5fecdec2..1c5d98ec 100644 --- a/src/legacy/getusershell.c +++ b/src/legacy/getusershell.c @@ -25,8 +25,10 @@ char *getusershell(void) ssize_t l; if (!f) setusershell(); if (!f) return 0; - l = getline(&line, &linesize, f); - if (l <= 0) return 0; + do { + l = getline(&line, &linesize, f); + if (l <= 0) return 0; + } while (line[0] == '#' || line[0] == '\n'); if (line[l-1]=='\n') line[l-1]=0; return line; } diff --git a/src/linux/renameat2.c b/src/linux/renameat2.c new file mode 100644 index 00000000..b8060388 --- /dev/null +++ b/src/linux/renameat2.c @@ -0,0 +1,11 @@ +#define _GNU_SOURCE +#include <stdio.h> +#include "syscall.h" + +int renameat2(int oldfd, const char *old, int newfd, const char *new, unsigned flags) +{ +#ifdef SYS_renameat + if (!flags) return syscall(SYS_renameat, oldfd, old, newfd, new); +#endif + return syscall(SYS_renameat2, oldfd, old, newfd, new, flags); +} diff --git a/src/linux/statx.c b/src/linux/statx.c index 4616bff4..4fb96e4b 100644 --- a/src/linux/statx.c +++ b/src/linux/statx.c @@ -19,8 +19,11 @@ int statx(int dirfd, const char *restrict path, int flags, unsigned mask, struct ret = fstatat(dirfd, path, &st, flags); if (ret) return ret; + *stx = (struct statx){0}; stx->stx_dev_major = major(st.st_dev); stx->stx_dev_minor = minor(st.st_dev); + stx->stx_rdev_major = major(st.st_rdev); + stx->stx_rdev_minor = minor(st.st_rdev); stx->stx_ino = st.st_ino; stx->stx_mode = st.st_mode; stx->stx_nlink = st.st_nlink; @@ -35,7 +38,6 @@ int statx(int dirfd, const char *restrict path, int flags, unsigned mask, struct stx->stx_mtime.tv_nsec = st.st_mtim.tv_nsec; stx->stx_ctime.tv_sec = st.st_ctim.tv_sec; stx->stx_ctime.tv_nsec = st.st_ctim.tv_nsec; - stx->stx_btime = (struct statx_timestamp){.tv_sec=0, .tv_nsec=0}; stx->stx_mask = STATX_BASIC_STATS; return 0; diff --git a/src/locale/bind_textdomain_codeset.c b/src/locale/bind_textdomain_codeset.c index 5ebfd5e8..240e83ed 100644 --- a/src/locale/bind_textdomain_codeset.c +++ b/src/locale/bind_textdomain_codeset.c @@ -5,7 +5,9 @@ char *bind_textdomain_codeset(const char *domainname, const char *codeset) { - if (codeset && strcasecmp(codeset, "UTF-8")) + if (codeset && strcasecmp(codeset, "UTF-8")) { errno = EINVAL; - return NULL; + return 0; + } + return "UTF-8"; } diff --git a/src/locale/codepages.h b/src/locale/codepages.h index 4e236ef3..a254f0f5 100644 --- a/src/locale/codepages.h +++ b/src/locale/codepages.h @@ -286,6 +286,17 @@ "\323\174\103\215\64\365\124\123\213\77\336\150\263\115\66\375\164\363\12\55" "\255\304\42\261\57\266\234\162\17\56\260\240\162\113\56\263\310\62\66\50" +"cp858\0" +"\0\40" +"\307\360\223\216\70\344\200\123\316\71\352\254\203\316\73\356\260\103\114\61" +"\311\230\143\14\75\366\310\263\117\76\377\130\303\15\76\243\140\163\15\135" +"\341\264\63\217\76\361\104\243\212\56\277\270\302\112\57\274\204\262\312\56" +"\140\207\55\66\315\72\7\43\14\60\251\104\375\163\321\113\213\122\212\315" +"\67\363\274\163\316\63\367\74\316\60\110\13\175\65\325\116\373\254\65\51" +"\360\100\243\314\62\310\220\334\214\63\317\340\134\163\327\134\233\302\314\326" +"\323\174\103\215\64\365\124\123\213\77\336\150\263\115\66\375\164\363\12\55" +"\255\304\42\261\57\266\234\162\17\56\260\240\162\113\56\263\310\62\66\50" + "cp866\0" "\0\40" "\337\201\27\236\170\343\221\127\236\171\347\241\227\236\172" 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 7fb2e1ef..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; @@ -339,6 +345,8 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri } else if (d-159 <= 252-159) { c++; d -= 159; + } else { + goto ilseq; } if (c>=84) goto ilseq; c = jis0208[c][d]; @@ -428,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; } @@ -500,7 +517,7 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri if (c >= 93 || d >= 94) { c += (0xa1-0x81); d += 0xa1; - if (c >= 93 || c>=0xc6-0x81 && d>0x52) + if (c > 0xc6-0x81 || c==0xc6-0x81 && d>0x52) goto ilseq; if (d-'A'<26) d = d-'A'; else if (d-'a'<26) d = d-'a'+26; @@ -543,6 +560,10 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri if (*outb < k) goto toobig; memcpy(*out, tmp, k); } else k = wctomb_utf8(*out, c); + /* This failure condition should be unreachable, but + * is included to prevent decoder bugs from translating + * into advancement outside the output buffer range. */ + if (k>4) goto ilseq; *out += k; *outb -= k; break; diff --git a/src/malloc/mallocng/glue.h b/src/malloc/mallocng/glue.h index 77f4c812..8c2586fb 100644 --- a/src/malloc/mallocng/glue.h +++ b/src/malloc/mallocng/glue.h @@ -62,8 +62,8 @@ __attribute__((__visibility__("hidden"))) extern int __malloc_lock[1]; #define LOCK_OBJ_DEF \ -int __malloc_lock[1]; \ -void __malloc_atfork(int who) { malloc_atfork(who); } +void __malloc_atfork(int who) { malloc_atfork(who); } \ +int __malloc_lock[1] static inline void rdlock() { diff --git a/src/math/powl.c b/src/math/powl.c index 6f64ea71..9eb22162 100644 --- a/src/math/powl.c +++ b/src/math/powl.c @@ -57,14 +57,6 @@ * IEEE 0,8700 60000 6.5e-18 1.0e-18 * 0.99 < x < 1.01, 0 < y < 8700, uniformly distributed. * - * - * ERROR MESSAGES: - * - * message condition value returned - * pow overflow x**y > MAXNUM INFINITY - * pow underflow x**y < 1/MAXNUM 0.0 - * pow domain x<0 and y noninteger 0.0 - * */ #include "libm.h" diff --git a/src/misc/initgroups.c b/src/misc/initgroups.c index 922a9581..101f5c7b 100644 --- a/src/misc/initgroups.c +++ b/src/misc/initgroups.c @@ -1,11 +1,29 @@ #define _GNU_SOURCE #include <grp.h> #include <limits.h> +#include <stdlib.h> int initgroups(const char *user, gid_t gid) { - gid_t groups[NGROUPS_MAX]; - int count = NGROUPS_MAX; - if (getgrouplist(user, gid, groups, &count) < 0) return -1; - return setgroups(count, groups); + gid_t buf[32], *groups = buf; + int count = sizeof buf / sizeof *buf, prev_count = count; + while (getgrouplist(user, gid, groups, &count) < 0) { + if (groups != buf) free(groups); + + /* Return if failure isn't buffer size */ + if (count <= prev_count) + return -1; + + /* Always increase by at least 50% to limit to + * logarithmically many retries on TOCTOU races. */ + if (count < prev_count + (prev_count>>1)) + count = prev_count + (prev_count>>1); + + groups = calloc(count, sizeof *groups); + if (!groups) return -1; + prev_count = count; + } + int ret = setgroups(count, groups); + if (groups != buf) free(groups); + return ret; } diff --git a/src/misc/mntent.c b/src/misc/mntent.c index 78bf0cd0..76f9c162 100644 --- a/src/misc/mntent.c +++ b/src/misc/mntent.c @@ -81,7 +81,7 @@ struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int bufle len = strlen(linebuf); if (len > INT_MAX) continue; for (i = 0; i < sizeof n / sizeof *n; i++) n[i] = len; - sscanf(linebuf, " %n%*[^ \t]%n %n%*[^ \t]%n %n%*[^ \t]%n %n%*[^ \t]%n %d %d", + sscanf(linebuf, " %n%*[^ \t\n]%n %n%*[^ \t\n]%n %n%*[^ \t\n]%n %n%*[^ \t\n]%n %d %d", n, n+1, n+2, n+3, n+4, n+5, n+6, n+7, &mnt->mnt_freq, &mnt->mnt_passno); } while (linebuf[n[0]] == '#' || n[1]==len); @@ -115,5 +115,13 @@ int addmntent(FILE *f, const struct mntent *mnt) char *hasmntopt(const struct mntent *mnt, const char *opt) { - return strstr(mnt->mnt_opts, opt); + size_t l = strlen(opt); + char *p = mnt->mnt_opts; + for (;;) { + if (!strncmp(p, opt, l) && (!p[l] || p[l]==',' || p[l]=='=')) + return p; + p = strchr(p, ','); + if (!p) return 0; + p++; + } } diff --git a/src/mq/x32/mq_open.c b/src/mq/x32/mq_open.c new file mode 100644 index 00000000..23481959 --- /dev/null +++ b/src/mq/x32/mq_open.c @@ -0,0 +1,22 @@ +#include <mqueue.h> +#include <fcntl.h> +#include <stdarg.h> +#include "syscall.h" + +mqd_t mq_open(const char *name, int flags, ...) +{ + mode_t mode = 0; + struct mq_attr *attr = 0; + long long attrbuf[8]; + if (*name == '/') name++; + if (flags & O_CREAT) { + va_list ap; + va_start(ap, flags); + mode = va_arg(ap, mode_t); + attr = va_arg(ap, struct mq_attr *); + if (attr) for (int i=0; i<8; i++) + attrbuf[i] = *(long *)((char *)attr + i*sizeof(long)); + va_end(ap); + } + return syscall(SYS_mq_open, name, flags, mode, attr?attrbuf:0); +} diff --git a/src/mq/x32/mq_setattr.c b/src/mq/x32/mq_setattr.c new file mode 100644 index 00000000..0c631175 --- /dev/null +++ b/src/mq/x32/mq_setattr.c @@ -0,0 +1,14 @@ +#include <mqueue.h> +#include "syscall.h" + +int mq_setattr(mqd_t mqd, const struct mq_attr *restrict new, struct mq_attr *restrict old) +{ + long long attr[8]; + if (new) for (int i=0; i<8; i++) + attr[i] = *(long *)((char *)new + i*sizeof(long)); + int ret = __syscall(SYS_mq_getsetattr, mqd, new?attr:0, old?attr:0); + if (ret < 0) return __syscall_ret(ret); + if (old) for (int i=0; i<8; i++) + *(long *)((char *)old + i*sizeof(long)) = attr[i]; + return 0; +} diff --git a/src/multibyte/mbsnrtowcs.c b/src/multibyte/mbsnrtowcs.c index 931192e2..47cbdc00 100644 --- a/src/multibyte/mbsnrtowcs.c +++ b/src/multibyte/mbsnrtowcs.c @@ -2,11 +2,13 @@ size_t mbsnrtowcs(wchar_t *restrict wcs, const char **restrict src, size_t n, size_t wn, mbstate_t *restrict st) { + static unsigned internal_state; size_t l, cnt=0, n2; wchar_t *ws, wbuf[256]; const char *s = *src; const char *tmp_s; + if (!st) st = (void *)&internal_state; if (!wcs) ws = wbuf, wn = sizeof wbuf / sizeof *wbuf; else ws = wcs; @@ -41,8 +43,8 @@ size_t mbsnrtowcs(wchar_t *restrict wcs, const char **restrict src, size_t n, si s = 0; break; } - /* have to roll back partial character */ - *(unsigned *)st = 0; + s += n; + n -= n; break; } s += l; n -= l; diff --git a/src/network/getifaddrs.c b/src/network/getifaddrs.c index 74df4d6c..55039bd8 100644 --- a/src/network/getifaddrs.c +++ b/src/network/getifaddrs.c @@ -13,8 +13,8 @@ /* getifaddrs() reports hardware addresses with PF_PACKET that implies * struct sockaddr_ll. But e.g. Infiniband socket address length is - * longer than sockaddr_ll.ssl_addr[8] can hold. Use this hack struct - * to extend ssl_addr - callers should be able to still use it. */ + * longer than sockaddr_ll.sll_addr[8] can hold. Use this hack struct + * to extend sll_addr - callers should be able to still use it. */ struct sockaddr_ll_hack { unsigned short sll_family, sll_protocol; int sll_ifindex; diff --git a/src/network/inet_ntop.c b/src/network/inet_ntop.c index 4bfef2c5..f442f47d 100644 --- a/src/network/inet_ntop.c +++ b/src/network/inet_ntop.c @@ -34,7 +34,12 @@ const char *inet_ntop(int af, const void *restrict a0, char *restrict s, socklen for (i=best=0, max=2; buf[i]; i++) { if (i && buf[i] != ':') continue; j = strspn(buf+i, ":0"); - if (j>max) best=i, max=j; + /* The leading sequence of zeros (best==0) is + * disadvantaged compared to sequences elsewhere + * as it doesn't have a leading colon. One extra + * character is required for another sequence to + * beat it fairly. */ + if (j>max+(best==0)) best=i, max=j; } if (max>3) { buf[best] = buf[best+1] = ':'; diff --git a/src/network/res_msend.c b/src/network/res_msend.c index 86c2fcf4..51d42ecb 100644 --- a/src/network/res_msend.c +++ b/src/network/res_msend.c @@ -83,8 +83,8 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries, int fd; int timeout, attempts, retry_interval, servfail_retry; union { - struct sockaddr_in sin; struct sockaddr_in6 sin6; + struct sockaddr_in sin; } sa = {0}, ns[MAXNS] = {{0}}; socklen_t sl = sizeof sa.sin; int nns = 0; @@ -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/passwd/getgr_a.c b/src/passwd/getgr_a.c index afeb1ece..84550404 100644 --- a/src/passwd/getgr_a.c +++ b/src/passwd/getgr_a.c @@ -71,6 +71,10 @@ int __getgr_a(const char *name, gid_t gid, struct group *gr, char **buf, size_t goto cleanup_f; } + if (groupbuf[GRMEMCNT] > (size_t)(INT32_MAX-1)) { + rv = ENOMEM; + goto cleanup_f; + } if (groupbuf[GRNAMELEN] > SIZE_MAX - groupbuf[GRPASSWDLEN]) { rv = ENOMEM; goto cleanup_f; @@ -127,7 +131,13 @@ int __getgr_a(const char *name, gid_t gid, struct group *gr, char **buf, size_t if (groupbuf[GRMEMCNT]) { mem[0][0] = *buf + groupbuf[GRNAMELEN] + groupbuf[GRPASSWDLEN]; for (ptr = mem[0][0], i = 0; ptr != mem[0][0]+grlist_len; ptr++) - if (!*ptr) mem[0][++i] = ptr+1; + if (!*ptr) + if (i<groupbuf[GRMEMCNT]) { + mem[0][++i] = ptr+1; + } else { + rv = EIO; + goto cleanup_f; + } mem[0][i] = 0; if (i != groupbuf[GRMEMCNT]) { 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/setjmp/riscv32/longjmp.S b/src/setjmp/riscv32/longjmp.S index f9cb3318..b4e5458d 100644 --- a/src/setjmp/riscv32/longjmp.S +++ b/src/setjmp/riscv32/longjmp.S @@ -23,18 +23,24 @@ longjmp: lw ra, 52(a0) #ifndef __riscv_float_abi_soft - fld fs0, 56(a0) - fld fs1, 64(a0) - fld fs2, 72(a0) - fld fs3, 80(a0) - fld fs4, 88(a0) - fld fs5, 96(a0) - fld fs6, 104(a0) - fld fs7, 112(a0) - fld fs8, 120(a0) - fld fs9, 128(a0) - fld fs10, 136(a0) - fld fs11, 144(a0) +#ifdef __riscv_float_abi_double +#define FLX fld +#else +#define FLX flw +#endif + + FLX fs0, 56(a0) + FLX fs1, 64(a0) + FLX fs2, 72(a0) + FLX fs3, 80(a0) + FLX fs4, 88(a0) + FLX fs5, 96(a0) + FLX fs6, 104(a0) + FLX fs7, 112(a0) + FLX fs8, 120(a0) + FLX fs9, 128(a0) + FLX fs10, 136(a0) + FLX fs11, 144(a0) #endif seqz a0, a1 diff --git a/src/setjmp/riscv32/setjmp.S b/src/setjmp/riscv32/setjmp.S index 8a75cf55..5a1a41ef 100644 --- a/src/setjmp/riscv32/setjmp.S +++ b/src/setjmp/riscv32/setjmp.S @@ -23,18 +23,24 @@ setjmp: sw ra, 52(a0) #ifndef __riscv_float_abi_soft - fsd fs0, 56(a0) - fsd fs1, 64(a0) - fsd fs2, 72(a0) - fsd fs3, 80(a0) - fsd fs4, 88(a0) - fsd fs5, 96(a0) - fsd fs6, 104(a0) - fsd fs7, 112(a0) - fsd fs8, 120(a0) - fsd fs9, 128(a0) - fsd fs10, 136(a0) - fsd fs11, 144(a0) +#ifdef __riscv_float_abi_double +#define FSX fsd +#else +#define FSX fsw +#endif + + FSX fs0, 56(a0) + FSX fs1, 64(a0) + FSX fs2, 72(a0) + FSX fs3, 80(a0) + FSX fs4, 88(a0) + FSX fs5, 96(a0) + FSX fs6, 104(a0) + FSX fs7, 112(a0) + FSX fs8, 120(a0) + FSX fs9, 128(a0) + FSX fs10, 136(a0) + FSX fs11, 144(a0) #endif li a0, 0 diff --git a/src/setjmp/riscv64/longjmp.S b/src/setjmp/riscv64/longjmp.S index 41e2d210..982475c7 100644 --- a/src/setjmp/riscv64/longjmp.S +++ b/src/setjmp/riscv64/longjmp.S @@ -23,18 +23,24 @@ longjmp: ld ra, 104(a0) #ifndef __riscv_float_abi_soft - fld fs0, 112(a0) - fld fs1, 120(a0) - fld fs2, 128(a0) - fld fs3, 136(a0) - fld fs4, 144(a0) - fld fs5, 152(a0) - fld fs6, 160(a0) - fld fs7, 168(a0) - fld fs8, 176(a0) - fld fs9, 184(a0) - fld fs10, 192(a0) - fld fs11, 200(a0) +#ifdef __riscv_float_abi_double +#define FLX fld +#else +#define FLX flw +#endif + + FLX fs0, 112(a0) + FLX fs1, 120(a0) + FLX fs2, 128(a0) + FLX fs3, 136(a0) + FLX fs4, 144(a0) + FLX fs5, 152(a0) + FLX fs6, 160(a0) + FLX fs7, 168(a0) + FLX fs8, 176(a0) + FLX fs9, 184(a0) + FLX fs10, 192(a0) + FLX fs11, 200(a0) #endif seqz a0, a1 diff --git a/src/setjmp/riscv64/setjmp.S b/src/setjmp/riscv64/setjmp.S index 51249672..0795bf7d 100644 --- a/src/setjmp/riscv64/setjmp.S +++ b/src/setjmp/riscv64/setjmp.S @@ -23,18 +23,24 @@ setjmp: sd ra, 104(a0) #ifndef __riscv_float_abi_soft - fsd fs0, 112(a0) - fsd fs1, 120(a0) - fsd fs2, 128(a0) - fsd fs3, 136(a0) - fsd fs4, 144(a0) - fsd fs5, 152(a0) - fsd fs6, 160(a0) - fsd fs7, 168(a0) - fsd fs8, 176(a0) - fsd fs9, 184(a0) - fsd fs10, 192(a0) - fsd fs11, 200(a0) +#ifdef __riscv_float_abi_double +#define FSX fsd +#else +#define FSX fsw +#endif + + FSX fs0, 112(a0) + FSX fs1, 120(a0) + FSX fs2, 128(a0) + FSX fs3, 136(a0) + FSX fs4, 144(a0) + FSX fs5, 152(a0) + FSX fs6, 160(a0) + FSX fs7, 168(a0) + FSX fs8, 176(a0) + FSX fs9, 184(a0) + FSX fs10, 192(a0) + FSX fs11, 200(a0) #endif li a0, 0 diff --git a/src/signal/riscv32/restore.s b/src/signal/riscv32/restore.s index 40012c75..5a0af695 100644 --- a/src/signal/riscv32/restore.s +++ b/src/signal/riscv32/restore.s @@ -1,7 +1,9 @@ .global __restore +.hidden __restore .type __restore, %function __restore: .global __restore_rt +.hidden __restore_rt .type __restore_rt, %function __restore_rt: li a7, 139 # SYS_rt_sigreturn diff --git a/src/signal/riscv64/restore.s b/src/signal/riscv64/restore.s index 40012c75..5a0af695 100644 --- a/src/signal/riscv64/restore.s +++ b/src/signal/riscv64/restore.s @@ -1,7 +1,9 @@ .global __restore +.hidden __restore .type __restore, %function __restore: .global __restore_rt +.hidden __restore_rt .type __restore_rt, %function __restore_rt: li a7, 139 # SYS_rt_sigreturn diff --git a/src/signal/sigaltstack.c b/src/signal/sigaltstack.c index d3a6e821..616625c5 100644 --- a/src/signal/sigaltstack.c +++ b/src/signal/sigaltstack.c @@ -1,11 +1,13 @@ #include <signal.h> #include <errno.h> +#include <unistd.h> #include "syscall.h" int sigaltstack(const stack_t *restrict ss, stack_t *restrict old) { if (ss) { - if (!(ss->ss_flags & SS_DISABLE) && ss->ss_size < MINSIGSTKSZ) { + size_t min = sysconf(_SC_MINSIGSTKSZ); + if (!(ss->ss_flags & SS_DISABLE) && ss->ss_size < min) { errno = ENOMEM; return -1; } diff --git a/src/signal/siglongjmp.c b/src/signal/siglongjmp.c index bc317acc..53789b23 100644 --- a/src/signal/siglongjmp.c +++ b/src/signal/siglongjmp.c @@ -5,5 +5,10 @@ _Noreturn void siglongjmp(sigjmp_buf buf, int ret) { + /* If sigsetjmp was called with nonzero savemask flag, the address + * longjmp will return to is inside of sigsetjmp. The signal mask + * will then be restored in the returned-to context instead of here, + * which matters if the context we are returning from may not have + * sufficient stack space for signal delivery. */ longjmp(buf, ret); } diff --git a/src/signal/sigpause.c b/src/signal/sigpause.c index 363d2fec..1587c391 100644 --- a/src/signal/sigpause.c +++ b/src/signal/sigpause.c @@ -4,6 +4,6 @@ int sigpause(int sig) { sigset_t mask; sigprocmask(0, 0, &mask); - sigdelset(&mask, sig); + if (sigdelset(&mask, sig)) return -1; return sigsuspend(&mask); } diff --git a/src/stdio/__stdio_write.c b/src/stdio/__stdio_write.c index d2d89475..5356553d 100644 --- a/src/stdio/__stdio_write.c +++ b/src/stdio/__stdio_write.c @@ -11,6 +11,11 @@ size_t __stdio_write(FILE *f, const unsigned char *buf, size_t len) size_t rem = iov[0].iov_len + iov[1].iov_len; int iovcnt = 2; ssize_t cnt; + + if (!iov->iov_len) { + iov++; + iovcnt--; + } for (;;) { cnt = syscall(SYS_writev, f->fd, iov, iovcnt); if (cnt == rem) { diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c index 497c5e19..514a44dd 100644 --- a/src/stdio/vfprintf.c +++ b/src/stdio/vfprintf.c @@ -166,7 +166,8 @@ static char *fmt_u(uintmax_t x, char *s) { unsigned long y; for ( ; x>ULONG_MAX; x/=10) *--s = '0' + x%10; - for (y=x; y; y/=10) *--s = '0' + y%10; + for (y=x; y>=10; y/=10) *--s = '0' + y%10; + if (y) *--s = '0' + y; return s; } @@ -177,10 +178,16 @@ static char *fmt_u(uintmax_t x, char *s) typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)]; #endif -static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t) +static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t, int ps) { - uint32_t big[(LDBL_MANT_DIG+28)/29 + 1 // mantissa expansion - + (LDBL_MAX_EXP+LDBL_MANT_DIG+28+8)/9]; // exponent expansion + int max_mant_dig = (ps==BIGLPRE) ? LDBL_MANT_DIG : DBL_MANT_DIG; + int max_exp = (ps==BIGLPRE) ? LDBL_MAX_EXP : DBL_MAX_EXP; + /* One slot for 29 bits left of radix point, a slot for every 29-21=8 + * bits right of the radix point, and one final zero slot. */ + int max_mant_slots = 1 + (max_mant_dig-29+7)/8 + 1; + int max_exp_slots = (max_exp+max_mant_dig+28+8)/9; + int bufsize = max_mant_slots + max_exp_slots; + uint32_t big[bufsize]; uint32_t *a, *d, *r, *z; int e2=0, e, i, j, l; char buf[9+LDBL_MANT_DIG/4], *s; @@ -211,18 +218,11 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t) if (y) e2--; if ((t|32)=='a') { - long double round = 8.0; - int re; - if (t&32) prefix += 9; pl += 2; - if (p<0 || p>=LDBL_MANT_DIG/4-1) re=0; - else re=LDBL_MANT_DIG/4-1-p; - - if (re) { - round *= 1<<(LDBL_MANT_DIG%4); - while (re--) round*=16; + if (p>=0 && p<(LDBL_MANT_DIG-1+3)/4) { + double round = scalbn(1, LDBL_MANT_DIG-1-(p*4)); if (*prefix=='-') { y=-y; y-=round; @@ -268,7 +268,7 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t) if (y) y *= 0x1p28, e2-=28; if (e2<0) a=r=z=big; - else a=r=z=big+sizeof(big)/sizeof(*big) - LDBL_MANT_DIG - 1; + else a=r=z=big+sizeof(big)/sizeof(*big) - max_mant_slots - 1; do { *z = y; @@ -563,11 +563,11 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, case 'x': case 'X': a = fmt_x(arg.i, z, t&32); if (arg.i && (fl & ALT_FORM)) prefix+=(t>>4), pl=2; - if (0) { + goto ifmt_tail; case 'o': a = fmt_o(arg.i, z); if ((fl&ALT_FORM) && p<z-a+1) p=z-a+1; - } if (0) { + goto ifmt_tail; case 'd': case 'i': pl=1; if (arg.i>INTMAX_MAX) { @@ -579,7 +579,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, } else pl=0; case 'u': a = fmt_u(arg.i, z); - } + ifmt_tail: if (xp && p<0) goto overflow; if (xp) fl &= ~ZERO_PAD; if (!arg.i && !p) { @@ -624,7 +624,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, case 'e': case 'f': case 'g': case 'a': case 'E': case 'F': case 'G': case 'A': if (xp && p<0) goto overflow; - l = fmt_fp(f, arg.f, w, p, fl, t); + l = fmt_fp(f, arg.f, w, p, fl, t, ps); if (l<0) goto overflow; continue; } diff --git a/src/stdlib/qsort.c b/src/stdlib/qsort.c index 314ddc29..28607450 100644 --- a/src/stdlib/qsort.c +++ b/src/stdlib/qsort.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2011 by Valentin Ochs +/* Copyright (C) 2011 by Lynn Ochs * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -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/string/strcasestr.c b/src/string/strcasestr.c index af109f36..dc598bc3 100644 --- a/src/string/strcasestr.c +++ b/src/string/strcasestr.c @@ -4,6 +4,7 @@ char *strcasestr(const char *h, const char *n) { size_t l = strlen(n); + if (!l) return (char *)h; for (; *h; h++) if (!strncasecmp(h, n, l)) return (char *)h; return 0; } diff --git a/src/termios/cfgetospeed.c b/src/termios/cfgetospeed.c index 55fa6f55..de46a1d8 100644 --- a/src/termios/cfgetospeed.c +++ b/src/termios/cfgetospeed.c @@ -9,5 +9,5 @@ speed_t cfgetospeed(const struct termios *tio) speed_t cfgetispeed(const struct termios *tio) { - return cfgetospeed(tio); + return (tio->c_cflag & CIBAUD) / (CIBAUD/CBAUD); } diff --git a/src/termios/cfsetospeed.c b/src/termios/cfsetospeed.c index c9cbdd9d..3eab092a 100644 --- a/src/termios/cfsetospeed.c +++ b/src/termios/cfsetospeed.c @@ -16,7 +16,11 @@ int cfsetospeed(struct termios *tio, speed_t speed) int cfsetispeed(struct termios *tio, speed_t speed) { - return speed ? cfsetospeed(tio, speed) : 0; + if (speed & ~CBAUD) { + errno = EINVAL; + return -1; + } + tio->c_cflag &= ~CIBAUD; + tio->c_cflag |= speed * (CIBAUD/CBAUD); + return 0; } - -weak_alias(cfsetospeed, cfsetspeed); diff --git a/src/termios/cfsetspeed.c b/src/termios/cfsetspeed.c new file mode 100644 index 00000000..2c369db9 --- /dev/null +++ b/src/termios/cfsetspeed.c @@ -0,0 +1,11 @@ +#define _BSD_SOURCE +#include <termios.h> +#include <sys/ioctl.h> +#include <errno.h> + +int cfsetspeed(struct termios *tio, speed_t speed) +{ + int r = cfsetospeed(tio, speed); + if (!r) cfsetispeed(tio, 0); + return r; +} diff --git a/src/thread/aarch64/__set_thread_area.c b/src/thread/aarch64/__set_thread_area.c new file mode 100644 index 00000000..2ec788e8 --- /dev/null +++ b/src/thread/aarch64/__set_thread_area.c @@ -0,0 +1,27 @@ +#include <elf.h> +#include "libc.h" + +#define BITRANGE(a,b) (2*(1UL<<(b))-(1UL<<(a))) + +int __set_thread_area(void *p) +{ + __asm__ __volatile__ ("msr tpidr_el0,%0" : : "r"(p) : "memory"); + + /* Mask off hwcap bits for SME and unknown future features. This is + * necessary because SME is not safe to use without libc support for + * it, and we do not (yet) have such support. */ + for (size_t *v = libc.auxv; *v; v+=2) { + if (v[0]==AT_HWCAP) { + v[1] &= ~BITRANGE(42,63); /* 42-47 are SME */ + } else if (v[0]==AT_HWCAP2) { + v[1] &= ~(BITRANGE(23,30) + | BITRANGE(37,42) + | BITRANGE(57,62)); + } else if (v[0]==AT_HWCAP3 || v[0]==AT_HWCAP4) { + v[0] = AT_IGNORE; + v[1] = 0; + } + } + + return 0; +} diff --git a/src/thread/aarch64/__set_thread_area.s b/src/thread/aarch64/__set_thread_area.s deleted file mode 100644 index fd0df34b..00000000 --- a/src/thread/aarch64/__set_thread_area.s +++ /dev/null @@ -1,7 +0,0 @@ -.global __set_thread_area -.hidden __set_thread_area -.type __set_thread_area,@function -__set_thread_area: - msr tpidr_el0,x0 - mov w0,#0 - ret diff --git a/src/thread/aarch64/clone.s b/src/thread/aarch64/clone.s index e3c83395..aff8155b 100644 --- a/src/thread/aarch64/clone.s +++ b/src/thread/aarch64/clone.s @@ -24,7 +24,8 @@ __clone: // parent ret // child -1: ldp x1,x0,[sp],#16 +1: mov x29, 0 + ldp x1,x0,[sp],#16 blr x1 mov x8,#93 // SYS_exit svc #0 diff --git a/src/thread/arm/clone.s b/src/thread/arm/clone.s index bb0965da..4ff0c0e8 100644 --- a/src/thread/arm/clone.s +++ b/src/thread/arm/clone.s @@ -19,7 +19,8 @@ __clone: ldmfd sp!,{r4,r5,r6,r7} bx lr -1: mov r0,r6 +1: mov fp,#0 + mov r0,r6 bl 3f 2: mov r7,#1 svc 0 diff --git a/src/thread/loongarch64/clone.s b/src/thread/loongarch64/clone.s index a165b365..cb4aacfc 100644 --- a/src/thread/loongarch64/clone.s +++ b/src/thread/loongarch64/clone.s @@ -22,6 +22,7 @@ __clone: beqz $a0, 1f # whether child process jirl $zero, $ra, 0 # parent process return 1: + move $fp, $zero ld.d $t8, $sp, 0 # function pointer ld.d $a0, $sp, 8 # argument pointer jirl $ra, $t8, 0 # call the user's function diff --git a/src/thread/m68k/clone.s b/src/thread/m68k/clone.s index f6dfa06f..0134cf4e 100644 --- a/src/thread/m68k/clone.s +++ b/src/thread/m68k/clone.s @@ -18,7 +18,8 @@ __clone: beq 1f movem.l (%sp)+,%d2-%d5 rts -1: move.l %a1,-(%sp) +1: suba.l %fp,%fp + move.l %a1,-(%sp) jsr (%a0) move.l #1,%d0 trap #0 diff --git a/src/thread/microblaze/clone.s b/src/thread/microblaze/clone.s index b68cc5fc..64e3f074 100644 --- a/src/thread/microblaze/clone.s +++ b/src/thread/microblaze/clone.s @@ -22,7 +22,8 @@ __clone: rtsd r15, 8 nop -1: lwi r3, r1, 0 +1: add r19, r0, r0 + lwi r3, r1, 0 lwi r5, r1, 4 brald r15, r3 nop diff --git a/src/thread/mips/clone.s b/src/thread/mips/clone.s index 04463385..229b987e 100644 --- a/src/thread/mips/clone.s +++ b/src/thread/mips/clone.s @@ -27,7 +27,8 @@ __clone: addu $sp, $sp, 16 jr $ra nop -1: lw $25, 0($sp) +1: move $fp, $0 + lw $25, 0($sp) lw $4, 4($sp) jalr $25 nop diff --git a/src/thread/mips64/clone.s b/src/thread/mips64/clone.s index 2d86899a..8de3db6c 100644 --- a/src/thread/mips64/clone.s +++ b/src/thread/mips64/clone.s @@ -25,7 +25,8 @@ __clone: nop jr $ra nop -1: ld $25, 0($sp) # function pointer +1: move $fp, $0 + ld $25, 0($sp) # function pointer ld $4, 8($sp) # argument pointer jalr $25 # call the user's function nop diff --git a/src/thread/mipsn32/clone.s b/src/thread/mipsn32/clone.s index 4d3c8c7a..9571231a 100644 --- a/src/thread/mipsn32/clone.s +++ b/src/thread/mipsn32/clone.s @@ -25,7 +25,8 @@ __clone: nop jr $ra nop -1: lw $25, 0($sp) # function pointer +1: move $fp, $0 + lw $25, 0($sp) # function pointer lw $4, 4($sp) # argument pointer jalr $25 # call the user's function nop diff --git a/src/thread/or1k/clone.s b/src/thread/or1k/clone.s index 2473ac20..b41488a2 100644 --- a/src/thread/or1k/clone.s +++ b/src/thread/or1k/clone.s @@ -6,6 +6,8 @@ .hidden __clone .type __clone,@function __clone: + l.xori r11, r0, -4 + l.and r4, r4, r11 l.addi r4, r4, -8 l.sw 0(r4), r3 l.sw 4(r4), r6 @@ -23,7 +25,8 @@ __clone: l.jr r9 l.nop -1: l.lwz r11, 0(r1) +1: l.ori r2, r0, 0 + l.lwz r11, 0(r1) l.jalr r11 l.lwz r3, 4(r1) diff --git a/src/thread/riscv32/clone.s b/src/thread/riscv32/clone.s index 3102239d..e2116e33 100644 --- a/src/thread/riscv32/clone.s +++ b/src/thread/riscv32/clone.s @@ -8,6 +8,7 @@ .type __clone, %function __clone: # Save func and arg to stack + andi a1, a1, -16 addi a1, a1, -16 sw a0, 0(a1) sw a3, 4(a1) diff --git a/src/thread/riscv64/clone.s b/src/thread/riscv64/clone.s index db908248..0e6f41a8 100644 --- a/src/thread/riscv64/clone.s +++ b/src/thread/riscv64/clone.s @@ -8,6 +8,7 @@ .type __clone, %function __clone: # Save func and arg to stack + andi a1, a1, -16 addi a1, a1, -16 sd a0, 0(a1) sd a3, 8(a1) diff --git a/src/thread/s390x/__tls_get_offset.s b/src/thread/s390x/__tls_get_offset.s index 8ee92de8..056c9110 100644 --- a/src/thread/s390x/__tls_get_offset.s +++ b/src/thread/s390x/__tls_get_offset.s @@ -1,17 +1,17 @@ .global __tls_get_offset .type __tls_get_offset,%function __tls_get_offset: - stmg %r14, %r15, 112(%r15) - aghi %r15, -160 + ear %r3, %a0 + sllg %r3, %r3, 32 + ear %r3, %a1 - la %r2, 0(%r2, %r12) - brasl %r14, __tls_get_addr + la %r1, 0(%r2, %r12) - ear %r1, %a0 - sllg %r1, %r1, 32 - ear %r1, %a1 + lg %r0, 0(%r1) + sllg %r4, %r0, 3 + lg %r5, 8(%r3) + lg %r2, 0(%r4, %r5) + ag %r2, 8(%r1) + sgr %r2, %r3 - sgr %r2, %r1 - - lmg %r14, %r15, 272(%r15) br %r14 diff --git a/src/thread/sem_post.c b/src/thread/sem_post.c index 5c2517f2..1c8f763c 100644 --- a/src/thread/sem_post.c +++ b/src/thread/sem_post.c @@ -16,6 +16,6 @@ int sem_post(sem_t *sem) if (waiters <= 1) new &= ~0x80000000; } while (a_cas(sem->__val, val, new) != val); - if (val<0) __wake(sem->__val, waiters>1 ? 1 : -1, priv); + if (val<0 || waiters) __wake(sem->__val, waiters>1 ? 1 : -1, priv); return 0; } diff --git a/src/time/__tz.c b/src/time/__tz.c index c34b3eb7..cfce268e 100644 --- a/src/time/__tz.c +++ b/src/time/__tz.c @@ -24,7 +24,6 @@ weak_alias(__tzname, tzname); static char std_name[TZNAME_MAX+1]; static char dst_name[TZNAME_MAX+1]; -const char __utc[] = "UTC"; static int dst_off; static int r0[5], r1[5]; @@ -437,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/__utc.c b/src/time/__utc.c new file mode 100644 index 00000000..9e8bfc58 --- /dev/null +++ b/src/time/__utc.c @@ -0,0 +1,3 @@ +#include "time_impl.h" + +const char __utc[] = "UTC"; diff --git a/src/time/strptime.c b/src/time/strptime.c index c54a0d8c..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) { @@ -59,6 +60,22 @@ char *strptime(const char *restrict s, const char *restrict f, struct tm *restri s = strptime(s, "%m/%d/%y", tm); if (!s) return 0; break; + case 'F': + /* Use temp buffer to implement the odd requirement + * that entire field be width-limited but the year + * subfield not itself be limited. */ + i = 0; + char tmp[20]; + if (*s == '-' || *s == '+') tmp[i++] = *s++; + while (*s=='0' && isdigit(s[1])) s++; + for (; *s && i<(size_t)w && i+1<sizeof tmp; i++) { + tmp[i] = *s++; + } + tmp[i] = 0; + char *p = strptime(tmp, "%12Y-%m-%d", tm); + if (!p) return 0; + s -= tmp+i-p; + break; case 'H': dest = &tm->tm_hour; min = 0; @@ -114,6 +131,13 @@ char *strptime(const char *restrict s, const char *restrict f, struct tm *restri s = strptime(s, "%H:%M", tm); if (!s) return 0; break; + case 's': + /* Parse only. Effect on tm is unspecified + * and presently no effect is implemented.. */ + if (*s == '-') s++; + if (!isdigit(*s)) return 0; + while (isdigit(*s)) s++; + break; case 'S': dest = &tm->tm_sec; min = 0; @@ -125,11 +149,30 @@ char *strptime(const char *restrict s, const char *restrict f, struct tm *restri break; case 'U': case 'W': - /* Throw away result, for now. (FIXME?) */ + /* Throw away result of %U, %V, %W, %g, and %G. Effect + * is unspecified and there is no clear right choice. */ dest = &dummy; min = 0; range = 54; goto numeric_range; + case 'V': + dest = &dummy; + min = 1; + range = 53; + goto numeric_range; + case 'g': + dest = &dummy; + w = 2; + goto numeric_digits; + case 'G': + dest = &dummy; + if (w<0) w=4; + goto numeric_digits; + case 'u': + dest = &tm->tm_wday; + min = 1; + range = 7; + goto numeric_range; case 'w': dest = &tm->tm_wday; min = 0; @@ -154,6 +197,20 @@ char *strptime(const char *restrict s, const char *restrict f, struct tm *restri adj = 1900; want_century = 0; goto numeric_digits; + case 'z': + if (*s == '+') neg = 0; + else if (*s == '-') neg = 1; + else return 0; + for (i=0; i<4; i++) if (!isdigit(s[1+i])) return 0; + tm->__tm_gmtoff = (s[1]-'0')*36000+(s[2]-'0')*3600 + + (s[3]-'0')*600 + (s[4]-'0')*60; + if (neg) tm->__tm_gmtoff = -tm->__tm_gmtoff; + s += 5; + break; + case 'Z': + i = __tzname_to_isdst(&s); + if (i>=0) tm->tm_isdst = i; + break; case '%': if (*s++ != '%') return 0; break; 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); diff --git a/src/time/timer_create.c b/src/time/timer_create.c index 9216b3ab..cc6c2236 100644 --- a/src/time/timer_create.c +++ b/src/time/timer_create.c @@ -1,6 +1,7 @@ #include <time.h> #include <setjmp.h> #include <limits.h> +#include <semaphore.h> #include "pthread_impl.h" #include "atomic.h" @@ -12,7 +13,7 @@ struct ksigevent { }; struct start_args { - pthread_barrier_t b; + sem_t sem1, sem2; struct sigevent *sev; }; @@ -21,10 +22,16 @@ static void dummy_0() } weak_alias(dummy_0, __pthread_tsd_run_dtors); +static void timer_handler(int sig, siginfo_t *si, void *ctx) +{ +} + static void cleanup_fromsig(void *p) { pthread_t self = __pthread_self(); __pthread_tsd_run_dtors(); + __block_app_sigs(0); + __syscall(SYS_rt_sigprocmask, SIG_BLOCK, SIGTIMER_SET, 0, _NSIG/8); self->cancel = 0; self->cancelbuf = 0; self->canceldisable = 0; @@ -42,7 +49,14 @@ static void *start(void *arg) void (*notify)(union sigval) = args->sev->sigev_notify_function; union sigval val = args->sev->sigev_value; - pthread_barrier_wait(&args->b); + /* The two-way semaphore synchronization ensures that we see + * self->cancel set by the parent if timer creation failed or + * self->timer_id if it succeeded, and informs the parent that + * we are done accessing the arguments so that the parent can + * proceed past their block lifetime. */ + while (sem_wait(&args->sem1)); + sem_post(&args->sem2); + if (self->cancel) return 0; for (;;) { @@ -90,7 +104,10 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict break; case SIGEV_THREAD: if (!init) { - struct sigaction sa = { .sa_handler = SIG_DFL }; + struct sigaction sa = { + .sa_sigaction = timer_handler, + .sa_flags = SA_SIGINFO | SA_RESTART + }; __libc_sigaction(SIGTIMER, &sa, 0); a_store(&init, 1); } @@ -99,7 +116,8 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict else pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_barrier_init(&args.b, 0, 2); + sem_init(&args.sem1, 0, 0); + sem_init(&args.sem2, 0, 0); args.sev = evp; __block_app_sigs(&set); @@ -120,7 +138,8 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict td->cancel = 1; } td->timer_id = timerid; - pthread_barrier_wait(&args.b); + sem_post(&args.sem1); + while (sem_wait(&args.sem2)); if (timerid < 0) return -1; *res = (void *)(INTPTR_MIN | (uintptr_t)td>>1); break; diff --git a/src/unistd/isatty.c b/src/unistd/isatty.c index 75a9c186..21222eda 100644 --- a/src/unistd/isatty.c +++ b/src/unistd/isatty.c @@ -6,8 +6,6 @@ int isatty(int fd) { struct winsize wsz; - unsigned long r = syscall(SYS_ioctl, fd, TIOCGWINSZ, &wsz); - if (r == 0) return 1; - if (errno != EBADF) errno = ENOTTY; - return 0; + /* +1 converts from error status (0/-1) to boolean (1/0) */ + return syscall(SYS_ioctl, fd, TIOCGWINSZ, &wsz) + 1; } diff --git a/src/unistd/pause.c b/src/unistd/pause.c index 90bbf4ca..90cc8db5 100644 --- a/src/unistd/pause.c +++ b/src/unistd/pause.c @@ -3,9 +3,5 @@ int pause(void) { -#ifdef SYS_pause - return syscall_cp(SYS_pause); -#else - return syscall_cp(SYS_ppoll, 0, 0, 0, 0); -#endif + return sys_pause_cp(); } |
