Make more fixes and improvements

- Remove PAGESIZE constant
- Fix realloc() documentation
- Fix ttyname_r() error reporting
- Make forking more reliable on Windows
- Make execvp() a few microseconds faster
- Make system() a few microseconds faster
- Tighten up the socket-related magic numbers
- Loosen restrictions on mmap() offset alignment
- Improve GetProgramExecutableName() with getenv("_")
- Use mkstemp() as basis for mktemp(), tmpfile(), tmpfd()
- Fix flakes in pthread_cancel_test, unix_test, fork_test
- Fix recently introduced futex stack overflow regression
- Let sockets be passed as stdio to subprocesses on Windows
- Improve security of bind() on Windows w/ SO_EXCLUSIVEADDRUSE
This commit is contained in:
Justine Tunney 2023-07-29 18:44:15 -07:00
parent 140a8a52e5
commit 18bb5888e1
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
311 changed files with 1239 additions and 2622 deletions

View file

@ -1,7 +1,6 @@
#include "libc/mem/arena.h"
#include "third_party/chibicc/chibicc.h"
#include "libc/runtime/internal.h"
#include "libc/x/x.h"
#include "third_party/chibicc/chibicc.h"
#include "tool/build/lib/getargs.h"
int main(int argc, char **argv) {

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/bits.h"
#include "libc/intrin/bsr.h"
#include "libc/mem/alg.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
@ -281,9 +282,13 @@ static int CompareDoxIndexEntry(const void *p1, const void *p2, void *arg) {
return strcasecmp(s1, s2);
}
static unsigned long roundup2pow(unsigned long x) {
return x > 1 ? 2ul << _bsrl(x - 1) : x ? 1 : 0;
}
static void IndexDox(struct Dox *dox) {
size_t i, j, n;
dox->names.n = _roundup2pow(dox->objects.n + dox->macros.n) << 1;
dox->names.n = roundup2pow(dox->objects.n + dox->macros.n) << 1;
dox->names.p = calloc(dox->names.n, sizeof(*dox->names.p));
n = 0;
for (i = 0; i < dox->objects.n; ++i) {

View file

@ -24,7 +24,6 @@
#include "libc/fmt/libgen.h"
#include "libc/log/libfatal.internal.h"
#include "libc/mem/arena.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/x/xasprintf.h"
@ -267,7 +266,6 @@ static Token *read_const_expr(Token **rest, Token *tok) {
// Read and evaluate a constant expression.
static long eval_const_expr(Token **rest, Token *tok) {
__arena_push();
Token *start = tok;
Token *expr = read_const_expr(rest, tok->next);
expr = preprocess2(expr);
@ -290,7 +288,6 @@ static long eval_const_expr(Token **rest, Token *tok) {
if (rest2->kind != TK_EOF && rest2->kind != TK_JAVADOWN) {
error_tok(rest2, "extra token");
}
__arena_pop();
return val;
}

View file

@ -68,7 +68,7 @@ typedef struct sCppState {
boolean hasAtLiteralStrings; /* supports @"c:\" strings */
struct sDirective {
enum eState state; /* current directive being processed */
boolean accept; /* is a directive syntactically permitted? */
boolean accept_; /* is a directive syntactically permitted? */
vString * name; /* macro name */
unsigned int nestLevel; /* level 0 is not used */
conditionalInfo ifdef [MaxCppNestingLevel];
@ -120,7 +120,7 @@ extern void cppInit (const boolean state, const boolean hasAtLiteralStrings)
Cpp.hasAtLiteralStrings = hasAtLiteralStrings;
Cpp.directive.state = DRCTV_NONE;
Cpp.directive.accept = TRUE;
Cpp.directive.accept_ = TRUE;
Cpp.directive.nestLevel = 0;
Cpp.directive.ifdef [0].ignoreAllBranches = FALSE;
@ -564,25 +564,25 @@ process:
case NEWLINE:
if (directive && ! ignore)
directive = FALSE;
Cpp.directive.accept = TRUE;
Cpp.directive.accept_ = TRUE;
break;
case DOUBLE_QUOTE:
Cpp.directive.accept = FALSE;
Cpp.directive.accept_ = FALSE;
c = skipToEndOfString (FALSE);
break;
case '#':
if (Cpp.directive.accept)
if (Cpp.directive.accept_)
{
directive = TRUE;
Cpp.directive.state = DRCTV_HASH;
Cpp.directive.accept = FALSE;
Cpp.directive.state = DRCTV_HASH;
Cpp.directive.accept_ = FALSE;
}
break;
case SINGLE_QUOTE:
Cpp.directive.accept = FALSE;
Cpp.directive.accept_ = FALSE;
c = skipToEndOfChar ();
break;
@ -599,7 +599,7 @@ process:
fileUngetc (c);
}
else
Cpp.directive.accept = FALSE;
Cpp.directive.accept_ = FALSE;
break;
}
@ -649,12 +649,12 @@ process:
int next = fileGetc ();
if (next == DOUBLE_QUOTE)
{
Cpp.directive.accept = FALSE;
Cpp.directive.accept_ = FALSE;
c = skipToEndOfString (TRUE);
break;
}
}
Cpp.directive.accept = FALSE;
Cpp.directive.accept_ = FALSE;
if (directive)
ignore = handleDirective (c);
break;

View file

@ -1327,20 +1327,6 @@ void dlmalloc_atfork(void) {
}
#endif
void* dlvalloc(size_t bytes) {
size_t pagesz;
ensure_initialization();
pagesz = mparams.page_size;
return dlmemalign(pagesz, bytes);
}
void* dlpvalloc(size_t bytes) {
size_t pagesz;
ensure_initialization();
pagesz = mparams.page_size;
return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE));
}
void** dlindependent_calloc(size_t n_elements, size_t elem_size,
void* chunks[]) {
size_t sz = elem_size; /* serves as 1-element array */

View file

@ -98,13 +98,6 @@ void* dlmemalign(size_t, size_t);
*/
int dlposix_memalign(void**, size_t, size_t);
/*
valloc(size_t n);
Equivalent to memalign(pagesize, n), where pagesize is the page
size of the system. If the pagesize is unknown, 4096 is used.
*/
void* dlvalloc(size_t);
/*
mallopt(int parameter_number, int parameter_value)
Sets tunable parameters The format is to provide a
@ -348,13 +341,6 @@ void** dlindependent_comalloc(size_t, size_t*, void**);
*/
size_t dlbulk_free(void**, size_t n_elements);
/*
pvalloc(size_t n);
Equivalent to valloc(minimum-page-that-holds(n)), that is,
round up n to nearest pagesize.
*/
void* dlpvalloc(size_t);
/*
malloc_trim(size_t pad);

View file

@ -1140,7 +1140,8 @@ build_target_list (char *value)
void
init_hash_files (void)
{
hash_init (&files, 1000, file_hash_1, file_hash_2, file_hash_cmp);
// [jart] increased from 1000
hash_init (&files, 32768, file_hash_1, file_hash_2, file_hash_cmp);
}
/* EOF */

View file

@ -1,5 +1,4 @@
/* clang-format off */
/* clang-format off */
/* Locating a program in PATH.
Copyright (C) 2001-2003, 2009-2020 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.

View file

@ -2375,7 +2375,7 @@ exec_command (char **argv, char **envp)
/* Run the program. */
environ = envp;
execv (argv[0], argv);
execvp (argv[0], argv);
if(errno == ENOENT)
OSS (error, NILF, "%s: command doesn't exist: %s",

View file

@ -1036,6 +1036,10 @@ main (int argc, char **argv, char **envp)
#undef FATAL_SIG
#ifndef NDEBUG
ShowCrashReports();
#endif
/* Do not ignore the child-death signal. This must be done before
any children could possibly be created; otherwise, the wait
functions won't work on systems with the SVR4 ECHILD brain

View file

@ -253,7 +253,8 @@ strcache_add_len (const char *str, size_t len)
void
strcache_init (void)
{
hash_init (&strings, 8000, str_hash_1, str_hash_2, str_hash_cmp);
// [jart] increased from 8000
hash_init (&strings, 131072, str_hash_1, str_hash_2, str_hash_cmp);
}

View file

@ -26,6 +26,7 @@
#include "libc/calls/struct/timespec.h"
#include "libc/calls/struct/timespec.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/cosmo.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/atomic.h"
@ -41,7 +42,6 @@
#include "libc/sysv/errfuns.h"
#include "libc/thread/freebsd.internal.h"
#include "libc/thread/posixthread.internal.h"
#include "libc/thread/thread.h"
#include "libc/thread/tls.h"
#include "third_party/nsync/atomic.h"
#include "third_party/nsync/common.internal.h"
@ -55,29 +55,32 @@ errno_t _futex (atomic_int *, int, int, const struct timespec *, int *, int);
errno_t _futex_wake (atomic_int *, int, int) asm ("_futex");
int sys_futex_cp (atomic_int *, int, int, const struct timespec *, int *, int);
static int FUTEX_WAIT_;
static int FUTEX_PRIVATE_FLAG_;
static bool futex_is_supported;
static bool futex_timeout_is_relative;
static struct NsyncFutex {
_Atomic(uint32_t) once;
int FUTEX_WAIT_;
int FUTEX_PRIVATE_FLAG_;
bool is_supported;
bool timeout_is_relative;
} nsync_futex_;
__attribute__((__constructor__)) static void nsync_futex_init_ (void) {
static void nsync_futex_init_ (void) {
int e;
atomic_int x;
FUTEX_WAIT_ = FUTEX_WAIT;
nsync_futex_.FUTEX_WAIT_ = FUTEX_WAIT;
if (IsWindows ()) {
futex_is_supported = true;
nsync_futex_.is_supported = true;
return;
}
if (IsFreebsd ()) {
futex_is_supported = true;
FUTEX_PRIVATE_FLAG_ = FUTEX_PRIVATE_FLAG;
nsync_futex_.is_supported = true;
nsync_futex_.FUTEX_PRIVATE_FLAG_ = FUTEX_PRIVATE_FLAG;
return;
}
if (!(futex_is_supported = IsLinux () || IsOpenbsd ())) {
if (!(nsync_futex_.is_supported = IsLinux () || IsOpenbsd ())) {
return;
}
@ -96,22 +99,23 @@ __attribute__((__constructor__)) static void nsync_futex_init_ (void) {
if (IsLinux () &&
_futex (&x, FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME,
1, 0, 0, FUTEX_BITSET_MATCH_ANY) == -EAGAIN) {
FUTEX_WAIT_ = FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME;
FUTEX_PRIVATE_FLAG_ = FUTEX_PRIVATE_FLAG;
nsync_futex_.FUTEX_WAIT_ =
FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME;
nsync_futex_.FUTEX_PRIVATE_FLAG_ = FUTEX_PRIVATE_FLAG;
} else if (!IsTiny () && IsLinux () &&
_futex (&x, FUTEX_WAIT_BITSET, 1, 0, 0,
FUTEX_BITSET_MATCH_ANY) == -EAGAIN) {
FUTEX_WAIT_ = FUTEX_WAIT_BITSET;
FUTEX_PRIVATE_FLAG_ = FUTEX_PRIVATE_FLAG;
nsync_futex_.FUTEX_WAIT_ = FUTEX_WAIT_BITSET;
nsync_futex_.FUTEX_PRIVATE_FLAG_ = FUTEX_PRIVATE_FLAG;
} else if (IsOpenbsd () ||
(!IsTiny () && IsLinux () &&
!_futex_wake (&x, FUTEX_WAKE_PRIVATE, 1))) {
FUTEX_WAIT_ = FUTEX_WAIT;
FUTEX_PRIVATE_FLAG_ = FUTEX_PRIVATE_FLAG;
futex_timeout_is_relative = true;
nsync_futex_.FUTEX_WAIT_ = FUTEX_WAIT;
nsync_futex_.FUTEX_PRIVATE_FLAG_ = FUTEX_PRIVATE_FLAG;
nsync_futex_.timeout_is_relative = true;
} else {
FUTEX_WAIT_ = FUTEX_WAIT;
futex_timeout_is_relative = true;
nsync_futex_.FUTEX_WAIT_ = FUTEX_WAIT;
nsync_futex_.timeout_is_relative = true;
}
errno = e;
}
@ -197,7 +201,7 @@ static struct timespec *nsync_futex_timeout_ (struct timespec *memory,
struct timespec now;
if (!abstime) {
return 0;
} else if (!futex_timeout_is_relative) {
} else if (!nsync_futex_.timeout_is_relative) {
*memory = *abstime;
return memory;
} else {
@ -212,9 +216,11 @@ int nsync_futex_wait_ (atomic_int *w, int expect, char pshare, struct timespec *
struct PosixThread *pt = 0;
struct timespec tsmem, *timeout;
op = FUTEX_WAIT_;
cosmo_once (&nsync_futex_.once, nsync_futex_init_);
op = nsync_futex_.FUTEX_WAIT_;
if (pshare == PTHREAD_PROCESS_PRIVATE) {
op |= FUTEX_PRIVATE_FLAG_;
op |= nsync_futex_.FUTEX_PRIVATE_FLAG_;
}
if (abstime && timespec_cmp (*abstime, timespec_zero) <= 0) {
@ -234,7 +240,7 @@ int nsync_futex_wait_ (atomic_int *w, int expect, char pshare, struct timespec *
DescribeFutexOp (op), expect,
DescribeTimespec (0, timeout));
if (futex_is_supported) {
if (nsync_futex_.is_supported) {
e = errno;
if (IsWindows ()) {
// Windows 8 futexes don't support multiple processes :(
@ -296,12 +302,14 @@ int nsync_futex_wake_ (atomic_int *w, int count, char pshare) {
ASSERT (count == 1 || count == INT_MAX);
cosmo_once (&nsync_futex_.once, nsync_futex_init_);
op = FUTEX_WAKE;
if (pshare == PTHREAD_PROCESS_PRIVATE) {
op |= FUTEX_PRIVATE_FLAG_;
op |= nsync_futex_.FUTEX_PRIVATE_FLAG_;
}
if (futex_is_supported) {
if (nsync_futex_.is_supported) {
if (IsWindows ()) {
if (pshare) {
goto Polyfill;

View file

@ -48,7 +48,7 @@ $(THIRD_PARTY_NSYNC_A).pkg: \
$(THIRD_PARTY_NSYNC_A_OBJS) \
$(foreach x,$(THIRD_PARTY_NSYNC_A_DIRECTDEPS),$($(x)_A).pkg)
#$(THIRD_PARTY_NSYNC_A_OBJS): private \
$(THIRD_PARTY_NSYNC_A_OBJS): private \
CCFLAGS += \
-ffunction-sections \
-fdata-sections

View file

@ -904,7 +904,6 @@ if __name__ == 'PYOBJ.COM':
SO_PEERCRED = 0
SO_PEERSEC = 0
SO_PRIORITY = 0
SO_PROTOCOL = 0
SO_RCVBUF = 0
SO_RCVLOWAT = 0
SO_RCVTIMEO = 0

View file

@ -6760,7 +6760,6 @@ PyInit__socket(void)
PyModule_AddIntMacro(m, SO_DEBUG);
PyModule_AddIntMacro(m, SO_ACCEPTCONN);
if (SO_REUSEADDR) PyModule_AddIntMacro(m, SO_REUSEADDR);
if (SO_EXCLUSIVEADDRUSE) PyModule_AddIntMacro(m, SO_EXCLUSIVEADDRUSE);
PyModule_AddIntMacro(m, SO_KEEPALIVE);
PyModule_AddIntMacro(m, SO_DONTROUTE);
PyModule_AddIntMacro(m, SO_BROADCAST);
@ -6776,17 +6775,6 @@ PyInit__socket(void)
PyModule_AddIntMacro(m, SO_RCVTIMEO);
PyModule_AddIntMacro(m, SO_ERROR);
PyModule_AddIntMacro(m, SO_TYPE);
if (SO_SETFIB) PyModule_AddIntMacro(m, SO_SETFIB);
if (SO_PASSCRED) PyModule_AddIntMacro(m, SO_PASSCRED);
if (SO_PEERCRED) PyModule_AddIntMacro(m, SO_PEERCRED);
if (LOCAL_PEERCRED) PyModule_AddIntMacro(m, LOCAL_PEERCRED);
if (SO_PASSSEC) PyModule_AddIntMacro(m, SO_PASSSEC);
if (SO_PEERSEC) PyModule_AddIntMacro(m, SO_PEERSEC);
if (SO_BINDTODEVICE) PyModule_AddIntMacro(m, SO_BINDTODEVICE);
if (SO_PRIORITY) PyModule_AddIntMacro(m, SO_PRIORITY);
if (SO_MARK) PyModule_AddIntMacro(m, SO_MARK);
if (SO_DOMAIN) PyModule_AddIntMacro(m, SO_DOMAIN);
if (SO_PROTOCOL) PyModule_AddIntMacro(m, SO_PROTOCOL);
/* Maximum number of connections for "listen" */
PyModule_AddIntConstant(m, "SOMAXCONN", 0x80);
@ -6915,12 +6903,10 @@ PyInit__socket(void)
#endif
PyModule_AddIntMacro(m, IPPROTO_IP);
PyModule_AddIntMacro(m, IPPROTO_HOPOPTS);
PyModule_AddIntMacro(m, IPPROTO_ICMP);
PyModule_AddIntMacro(m, IPPROTO_TCP);
PyModule_AddIntMacro(m, IPPROTO_UDP);
PyModule_AddIntMacro(m, IPPROTO_RAW);
PyModule_AddIntMacro(m, IPPROTO_IGMP);
#ifdef IPPROTO_GGP
if (IPPROTO_GGP) PyModule_AddIntMacro(m, IPPROTO_GGP);
#endif