mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Fix bugs and make code tinier
- Fixed bug where stdio eof wasn't being sticky - Fixed bug where fseeko() wasn't clearing eof state - Removed assert() usage from libc favoring _unassert() / _npassert()
This commit is contained in:
parent
9b7c8db846
commit
d5910e2673
115 changed files with 510 additions and 290 deletions
|
@ -16,23 +16,60 @@ void __assert_fail(const char *, const char *, int) hidden relegated;
|
|||
#define static_assert _Static_assert
|
||||
#endif
|
||||
|
||||
#define _unassert(x) \
|
||||
do { \
|
||||
if (__builtin_expect(!(x), 0)) { \
|
||||
unreachable; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#ifdef __GNUC__
|
||||
#ifndef TINY
|
||||
/**
|
||||
* Specifies expression can't possibly be false.
|
||||
*
|
||||
* This macro uses the `notpossible` keyword and is intended for things
|
||||
* like systems integration, where we know for a fact that something is
|
||||
* never going to happen, but there's no proof. So we don't want to add
|
||||
* extra bloat for filenames and line numbers, since `ShowCrashReports`
|
||||
* can print a backtrace if we just embed the UD2 instruction to crash.
|
||||
* That's useful for systems code, for the following reason. Invariants
|
||||
* make sense with _unassert() since they usually get placed at the top
|
||||
* of functions. But if you used _unassert() to test a system call does
|
||||
* not fail, then check happens at the end of your function usually and
|
||||
* is therefore likely to result in a failure condition where execution
|
||||
* falls through into a different function, which is shocking to debug.
|
||||
*
|
||||
* In `MODE=tiny` these assertions are redefined as undefined behavior.
|
||||
*/
|
||||
#define _npassert(x) \
|
||||
do { \
|
||||
({ \
|
||||
if (__builtin_expect(!(x), 0)) { \
|
||||
notpossible; \
|
||||
} \
|
||||
} while (0)
|
||||
(void)0; \
|
||||
})
|
||||
#else
|
||||
#define _npassert(x) _unassert(x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
/**
|
||||
* Specifies expression being false is undefined behavior.
|
||||
*
|
||||
* This is a good way to tell the compiler about your invariants, which
|
||||
* leads to smaller faster programs. The expression is never removed by
|
||||
* the preprocessor so it's recommended that it be free of side-effects
|
||||
* if you intend for it to be removed. At the same time, this guarantee
|
||||
* makes this assertion useful for things like system calls, since they
|
||||
* won't be removed by `NDEBUG` mode.
|
||||
*
|
||||
* If this assertion fails, the worst possible things can happen unless
|
||||
* you've built your binary in `MODE=dbg` since UBSAN is the only thing
|
||||
* that's capable of debugging this macro.
|
||||
*/
|
||||
#define _unassert(x) \
|
||||
({ \
|
||||
if (__builtin_expect(!(x), 0)) { \
|
||||
unreachable; \
|
||||
} \
|
||||
(void)0; \
|
||||
})
|
||||
#endif
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -32,12 +32,10 @@
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
unsigned alarm(unsigned seconds) {
|
||||
int rc;
|
||||
struct itimerval it;
|
||||
bzero(&it, sizeof(it));
|
||||
it.it_value.tv_sec = seconds;
|
||||
rc = setitimer(ITIMER_REAL, &it, &it);
|
||||
assert(rc != -1);
|
||||
_npassert(!setitimer(ITIMER_REAL, &it, &it));
|
||||
if (!it.it_value.tv_sec && !it.it_value.tv_usec) {
|
||||
return 0;
|
||||
} else {
|
||||
|
|
|
@ -52,7 +52,7 @@ char *getcwd(char *buf, size_t size) {
|
|||
return 0;
|
||||
}
|
||||
} else if (_weaken(malloc)) {
|
||||
assert(!__vforked);
|
||||
_unassert(!__vforked);
|
||||
if (!size) size = PATH_MAX;
|
||||
if (!(p = _weaken(malloc)(size))) {
|
||||
STRACE("getcwd(%p, %'zu) %m", buf, size);
|
||||
|
|
|
@ -253,7 +253,7 @@ static int createHostInfo(struct NtIpAdapterAddresses *firstAdapter) {
|
|||
int count, i;
|
||||
|
||||
/* __hostInfo must be empty */
|
||||
assert(__hostInfo == NULL);
|
||||
_unassert(__hostInfo == NULL);
|
||||
|
||||
for (aa = firstAdapter; aa; aa = aa->Next) {
|
||||
/* Skip all the interfaces with no address and the ones that are not AF_INET
|
||||
|
|
|
@ -91,7 +91,7 @@ static long double nowl_art(void) {
|
|||
static long double nowl_vdso(void) {
|
||||
long double secs;
|
||||
struct timespec tv;
|
||||
assert(__gettime);
|
||||
_unassert(__gettime);
|
||||
__gettime(CLOCK_REALTIME_FAST, &tv);
|
||||
secs = tv.tv_nsec;
|
||||
secs *= 1 / 1e9L;
|
||||
|
|
|
@ -53,7 +53,7 @@ static textwindows int sys_open_nt_console(int dirfd,
|
|||
-1) {
|
||||
g_fds.p[fd].extra = sys_open_nt_impl(dirfd, mp->conout,
|
||||
(flags & ~O_ACCMODE) | O_WRONLY, mode);
|
||||
assert(g_fds.p[fd].extra != -1);
|
||||
_npassert(g_fds.p[fd].extra != -1);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
|
@ -52,7 +51,6 @@ ssize_t readlinkat(int dirfd, const char *path, char *buf, size_t bufsiz) {
|
|||
(bytes = __zipos_notat(dirfd, path)) == -1) {
|
||||
STRACE("TODO: zipos support for readlinkat");
|
||||
} else if (!IsWindows()) {
|
||||
assert(bufsiz);
|
||||
bytes = sys_readlinkat(dirfd, path, buf, bufsiz);
|
||||
} else {
|
||||
bytes = sys_readlinkat_nt(dirfd, path, buf, bufsiz);
|
||||
|
|
|
@ -181,7 +181,7 @@ skip_readlink:
|
|||
continue;
|
||||
}
|
||||
k = rc;
|
||||
assert(k <= p);
|
||||
_npassert(k <= p);
|
||||
if (k==p)
|
||||
goto toolong;
|
||||
if (!k) {
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
size_t uint64toarray_fixed16(uint64_t x, char b[hasatleast 17], uint8_t k) {
|
||||
char *p;
|
||||
assert(k <= 64 && !(k & 3));
|
||||
_unassert(k <= 64 && !(k & 3));
|
||||
for (p = b; k > 0;) *p++ = "0123456789abcdef"[(x >> (k -= 4)) & 15];
|
||||
*p = '\0';
|
||||
return p - b;
|
||||
|
|
|
@ -16,13 +16,13 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/mem/reverse.internal.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/divmod10.internal.h"
|
||||
#include "libc/fmt/fmt.internal.h"
|
||||
#include "libc/fmt/internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/mem/reverse.internal.h"
|
||||
|
||||
#define BUFFER_SIZE 144
|
||||
|
||||
|
@ -121,7 +121,7 @@ int __fmt_ntoa2(int out(const char *, void *, size_t), void *arg,
|
|||
}
|
||||
buf[len++] = alphabet[digit];
|
||||
} while (value);
|
||||
assert(count <= BUFFER_SIZE);
|
||||
_npassert(count <= BUFFER_SIZE);
|
||||
}
|
||||
return __fmt_ntoa_format(out, arg, buf, len, neg, log2base, prec, width,
|
||||
flags);
|
||||
|
|
|
@ -16,11 +16,10 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
int swprintf(wchar_t* ws, size_t n, const wchar_t* format, ...) {
|
||||
assert(!"not implemented");
|
||||
abort();
|
||||
kprintf("error: swprintf() not supported yet by cosmo libc sorry!\n");
|
||||
_Exit(1);
|
||||
}
|
||||
|
|
|
@ -23,10 +23,10 @@
|
|||
void *unhexbuf(void *buf, size_t size, const char *hexdigs) {
|
||||
size_t i;
|
||||
unsigned char *p;
|
||||
assert(size * 2 == strlen(hexdigs));
|
||||
_npassert(size * 2 == strlen(hexdigs));
|
||||
p = buf;
|
||||
for (i = 0; i < size; ++i) {
|
||||
assert(isxdigit(hexdigs[i / 2 + 0]) && isxdigit(hexdigs[i / 2 + 1]));
|
||||
_npassert(isxdigit(hexdigs[i / 2 + 0]) && isxdigit(hexdigs[i / 2 + 1]));
|
||||
}
|
||||
for (i = 0; i < size; ++i) {
|
||||
p[i] = hextoint(hexdigs[i * 2 + 0]) * 16 + hextoint(hexdigs[i * 2 + 1]);
|
||||
|
|
|
@ -61,7 +61,7 @@ noasan int __cxa_atexit(void *fp, void *arg, void *pred) {
|
|||
}
|
||||
}
|
||||
i = _bsr(~b->mask);
|
||||
assert(i < ARRAYLEN(b->p));
|
||||
_unassert(i < ARRAYLEN(b->p));
|
||||
b->mask |= 1u << i;
|
||||
b->p[i].fp = fp;
|
||||
b->p[i].arg = arg;
|
||||
|
|
|
@ -60,7 +60,7 @@ StartOverLocked:
|
|||
if (!pred) {
|
||||
b2 = b->next;
|
||||
if (b2) {
|
||||
assert(b != &__cxa_blocks.root);
|
||||
_npassert(b != &__cxa_blocks.root);
|
||||
if (_weaken(free)) {
|
||||
_weaken(free)(b);
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ const char *DescribeSockOptname(char[32], int, int);
|
|||
const char *DescribeSocketFamily(char[12], int);
|
||||
const char *DescribeSocketProtocol(char[12], int);
|
||||
const char *DescribeSocketType(char[64], int);
|
||||
const char *DescribeStdioState(char[12], int);
|
||||
const char *DescribeWhence(char[12], int);
|
||||
|
||||
#define DescribeArchPrctlCode(x) DescribeArchPrctlCode(alloca(12), x)
|
||||
|
@ -99,6 +100,7 @@ const char *DescribeWhence(char[12], int);
|
|||
#define DescribeSocketFamily(x) DescribeSocketFamily(alloca(12), x)
|
||||
#define DescribeSocketProtocol(x) DescribeSocketProtocol(alloca(12), x)
|
||||
#define DescribeSocketType(x) DescribeSocketType(alloca(64), x)
|
||||
#define DescribeStdioState(x) DescribeStdioState(alloca(12), x)
|
||||
#define DescribeWhence(x) DescribeWhence(alloca(12), x)
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
|
@ -34,10 +34,7 @@ const char *(DescribeOpenFlags)(char buf[128], int x) {
|
|||
struct DescribeFlags d[N];
|
||||
// TODO(jart): unify DescribeFlags and MagnumStr data structures
|
||||
for (n = 0; kOpenFlags[n].x != MAGNUM_TERMINATOR; ++n) {
|
||||
if (n == N) {
|
||||
assert(!"too many open flags");
|
||||
break;
|
||||
}
|
||||
if (n == N) notpossible;
|
||||
}
|
||||
for (i = 0; i < n; ++i) {
|
||||
d[i].flag = MAGNUM_NUMBER(kOpenFlags, i);
|
||||
|
|
29
libc/intrin/describestdiostate.c
Normal file
29
libc/intrin/describestdiostate.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
const char *(DescribeStdioState)(char buf[12], int x) {
|
||||
if (!x) return "";
|
||||
if (x == -1) return "EOF";
|
||||
if (x > 0) return _strerrno(x);
|
||||
FormatInt32(buf, x);
|
||||
return buf;
|
||||
}
|
|
@ -74,7 +74,7 @@ textwindows struct DirectMap sys_mmap_nt(void *addr, size_t size, int prot,
|
|||
}
|
||||
}
|
||||
} else {
|
||||
assert(flags & MAP_ANONYMOUS);
|
||||
_unassert(flags & MAP_ANONYMOUS);
|
||||
fl = (struct ProtectNt){kNtPageExecuteReadwrite,
|
||||
kNtFileMapWrite | kNtFileMapExecute};
|
||||
}
|
||||
|
|
|
@ -26,6 +26,6 @@
|
|||
* This function may only be called if IsWindows() is true.
|
||||
*/
|
||||
privileged bool(IsAtLeastWindows10)(void) {
|
||||
assert(IsWindows());
|
||||
_unassert(IsWindows());
|
||||
return IsAtLeastWindows10();
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
({ \
|
||||
typeof((a) + (b)) a_ = (a); \
|
||||
typeof(a_) b_ = (b); \
|
||||
assert(a_ >= 0); \
|
||||
assert(b_ >= 0); \
|
||||
_unassert(a_ >= 0); \
|
||||
_unassert(b_ >= 0); \
|
||||
asm("add\t%1,%0\n\t" \
|
||||
"rcr\t%0" \
|
||||
: "+r"(a_) \
|
||||
|
|
|
@ -56,14 +56,14 @@ errno_t pthread_once(pthread_once_t *once, void init(void)) {
|
|||
memory_order_acquire,
|
||||
memory_order_relaxed)) {
|
||||
init();
|
||||
atomic_store(&once->_lock, FINISHED);
|
||||
atomic_store_explicit(&once->_lock, FINISHED, memory_order_release);
|
||||
return 0;
|
||||
}
|
||||
// fallthrough
|
||||
case CALLING:
|
||||
do {
|
||||
pthread_yield();
|
||||
} while (atomic_load_explicit(&once->_lock, memory_order_relaxed) ==
|
||||
} while (atomic_load_explicit(&once->_lock, memory_order_acquire) ==
|
||||
CALLING);
|
||||
return 0;
|
||||
case FINISHED:
|
||||
|
|
|
@ -3,10 +3,11 @@
|
|||
#include "libc/intrin/likely.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
#define _KERNTRACE 0 /* not configurable w/ flag yet */
|
||||
#define _POLLTRACE 0 /* not configurable w/ flag yet */
|
||||
#define _DATATRACE 1 /* not configurable w/ flag yet */
|
||||
#define _NTTRACE 0 /* not configurable w/ flag yet */
|
||||
#define _KERNTRACE 0 /* not configurable w/ flag yet */
|
||||
#define _POLLTRACE 0 /* not configurable w/ flag yet */
|
||||
#define _DATATRACE 1 /* not configurable w/ flag yet */
|
||||
#define _STDIOTRACE 0 /* not configurable w/ flag yet */
|
||||
#define _NTTRACE 0 /* not configurable w/ flag yet */
|
||||
|
||||
#define STRACE_PROLOGUE "%rSYS %6P %'18T "
|
||||
|
||||
|
@ -42,6 +43,12 @@ COSMOPOLITAN_C_START_
|
|||
#define KERNTRACE(FMT, ...) (void)0
|
||||
#endif
|
||||
|
||||
#if defined(SYSDEBUG) && _STDIOTRACE
|
||||
#define STDIOTRACE(FMT, ...) STRACE(FMT, ##__VA_ARGS__)
|
||||
#else
|
||||
#define STDIOTRACE(FMT, ...) (void)0
|
||||
#endif
|
||||
|
||||
#if defined(SYSDEBUG) && _NTTRACE
|
||||
#define NTTRACE(FMT, ...) STRACE(FMT, ##__VA_ARGS__)
|
||||
#else
|
||||
|
|
|
@ -16,13 +16,13 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/mem/alg.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/countexpr.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/alg.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
|
@ -50,7 +50,7 @@ static void PrintHistogram(const long *h, size_t n, long t) {
|
|||
unsigned long logos;
|
||||
for (i = 0; i < n; ++i) {
|
||||
p = (h[i] * 10000 + (t >> 1)) / t;
|
||||
assert(0 <= p && p <= 10000);
|
||||
_unassert(0 <= p && p <= 10000);
|
||||
if (p) {
|
||||
for (j = 0; j < p / 100; ++j) s[j] = '#';
|
||||
s[j] = 0;
|
||||
|
|
|
@ -145,11 +145,11 @@ static void __memlog_update(void *p2, void *p) {
|
|||
__memlog.usage += n - __memlog.allocs.p[i].size;
|
||||
__memlog.allocs.p[i].addr = p2;
|
||||
__memlog.allocs.p[i].size = n;
|
||||
assert(__memlog.usage >= 0);
|
||||
_unassert(__memlog.usage >= 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
assert(!"this corruption");
|
||||
unreachable;
|
||||
}
|
||||
|
||||
static void __memlog_log(struct StackFrame *frame, const char *op, void *res,
|
||||
|
@ -169,21 +169,20 @@ static void __memlog_free(void *p) {
|
|||
__memlog.allocs.p[i].addr = 0;
|
||||
__memlog.usage -= __memlog.allocs.p[i].size;
|
||||
__memlog.allocs.f = MIN(__memlog.allocs.f, i);
|
||||
assert(__memlog.usage >= 0);
|
||||
_unassert(__memlog.usage >= 0);
|
||||
} else {
|
||||
kprintf("memlog could not find %p\n", p);
|
||||
assert(!"this corruption");
|
||||
n = -1;
|
||||
notpossible;
|
||||
}
|
||||
__memlog_unlock();
|
||||
assert(__memlog.free);
|
||||
_unassert(__memlog.free);
|
||||
__memlog.free(p);
|
||||
__memlog_log(__builtin_frame_address(0), "free", 0, p, n);
|
||||
}
|
||||
|
||||
static void *__memlog_malloc(size_t n) {
|
||||
void *res;
|
||||
assert(__memlog.malloc);
|
||||
_unassert(__memlog.malloc);
|
||||
if ((res = __memlog.malloc(n))) {
|
||||
__memlog_lock();
|
||||
__memlog_insert(res);
|
||||
|
@ -195,7 +194,7 @@ static void *__memlog_malloc(size_t n) {
|
|||
|
||||
static void *__memlog_calloc(size_t n, size_t z) {
|
||||
void *res;
|
||||
assert(__memlog.calloc);
|
||||
_unassert(__memlog.calloc);
|
||||
if ((res = __memlog.calloc(n, z))) {
|
||||
__memlog_lock();
|
||||
__memlog_insert(res);
|
||||
|
@ -207,7 +206,7 @@ static void *__memlog_calloc(size_t n, size_t z) {
|
|||
|
||||
static void *__memlog_memalign(size_t l, size_t n) {
|
||||
void *res;
|
||||
assert(__memlog.memalign);
|
||||
_unassert(__memlog.memalign);
|
||||
if ((res = __memlog.memalign(l, n))) {
|
||||
__memlog_lock();
|
||||
__memlog_insert(res);
|
||||
|
@ -221,7 +220,7 @@ static void *__memlog_realloc_impl(void *p, size_t n,
|
|||
void *(*f)(void *, size_t),
|
||||
struct StackFrame *frame) {
|
||||
void *res;
|
||||
assert(f);
|
||||
_unassert(f);
|
||||
if ((res = f(p, n))) {
|
||||
__memlog_lock();
|
||||
if (p) {
|
||||
|
|
|
@ -62,18 +62,13 @@ static wontreturn void __arena_die(void) {
|
|||
_exit(83);
|
||||
}
|
||||
|
||||
static wontreturn void __arena_not_implemented(void) {
|
||||
assert(!"not implemented");
|
||||
__arena_die();
|
||||
}
|
||||
|
||||
forceinline void __arena_check(void) {
|
||||
assert(__arena.depth);
|
||||
_unassert(__arena.depth);
|
||||
}
|
||||
|
||||
forceinline void __arena_check_pointer(void *p) {
|
||||
assert(BASE + __arena.offset[__arena.depth - 1] <= (uintptr_t)p &&
|
||||
(uintptr_t)p < BASE + __arena.offset[__arena.depth]);
|
||||
_unassert(BASE + __arena.offset[__arena.depth - 1] <= (uintptr_t)p &&
|
||||
(uintptr_t)p < BASE + __arena.offset[__arena.depth]);
|
||||
}
|
||||
|
||||
forceinline bool __arena_is_arena_pointer(void *p) {
|
||||
|
@ -326,7 +321,7 @@ void __arena_push(void) {
|
|||
if (!__arena.depth) {
|
||||
__arena_install();
|
||||
} else {
|
||||
assert(__arena.depth < ARRAYLEN(__arena.offset) - 1);
|
||||
_unassert(__arena.depth < ARRAYLEN(__arena.offset) - 1);
|
||||
}
|
||||
__arena.offset[__arena.depth + 1] = __arena.offset[__arena.depth];
|
||||
++__arena.depth;
|
||||
|
|
|
@ -25,9 +25,9 @@
|
|||
#include "libc/str/str.h"
|
||||
#include "libc/thread/tls.h"
|
||||
|
||||
static inline bool PointerNotOwnedByParentStackFrame(struct StackFrame *frame,
|
||||
struct StackFrame *parent,
|
||||
void *ptr) {
|
||||
forceinline bool PointerNotOwnedByParentStackFrame(struct StackFrame *frame,
|
||||
struct StackFrame *parent,
|
||||
void *ptr) {
|
||||
return !(((intptr_t)ptr > (intptr_t)frame) &&
|
||||
((intptr_t)ptr < (intptr_t)parent));
|
||||
}
|
||||
|
@ -93,8 +93,8 @@ static void DeferFunction(struct StackFrame *frame, void *fn, void *arg) {
|
|||
void __defer(void *rbp, void *fn, void *arg) {
|
||||
struct StackFrame *f, *frame = rbp;
|
||||
f = __builtin_frame_address(0);
|
||||
assert(f->next == frame);
|
||||
assert(PointerNotOwnedByParentStackFrame(f, frame, arg));
|
||||
_unassert(f->next == frame);
|
||||
_unassert(PointerNotOwnedByParentStackFrame(f, frame, arg));
|
||||
DeferFunction(frame, fn, arg);
|
||||
}
|
||||
|
||||
|
|
|
@ -52,9 +52,9 @@ struct Tarjan {
|
|||
|
||||
static bool TarjanPush(struct Tarjan *t, int v) {
|
||||
int *q;
|
||||
assert(t->S.i >= 0);
|
||||
assert(t->S.n >= 0);
|
||||
assert(0 <= v && v < t->Vn);
|
||||
_unassert(t->S.i >= 0);
|
||||
_unassert(t->S.n >= 0);
|
||||
_unassert(0 <= v && v < t->Vn);
|
||||
if (t->S.i == t->S.n) {
|
||||
if ((q = realloc(t->S.p, (t->S.n + (t->S.n >> 1) + 8) * sizeof(*t->S.p)))) {
|
||||
t->S.p = q;
|
||||
|
@ -67,13 +67,13 @@ static bool TarjanPush(struct Tarjan *t, int v) {
|
|||
}
|
||||
|
||||
static int TarjanPop(struct Tarjan *t) {
|
||||
assert(t->S.i > 0);
|
||||
_unassert(t->S.i > 0);
|
||||
return t->S.p[--t->S.i];
|
||||
}
|
||||
|
||||
static bool TarjanConnect(struct Tarjan *t, int v) {
|
||||
int fs, w, e;
|
||||
assert(0 <= v && v < t->Vn);
|
||||
_unassert(0 <= v && v < t->Vn);
|
||||
t->V[v].index = t->index;
|
||||
t->V[v].lowlink = t->index;
|
||||
t->V[v].onstack = true;
|
||||
|
@ -135,12 +135,12 @@ int _tarjan(int vertex_count, const int (*edges)[2], int edge_count,
|
|||
int *out_opt_componentcount) {
|
||||
int i, rc, v, e;
|
||||
struct Tarjan *t;
|
||||
assert(0 <= edge_count && edge_count <= INT_MAX);
|
||||
assert(0 <= vertex_count && vertex_count <= INT_MAX);
|
||||
_unassert(0 <= edge_count && edge_count <= INT_MAX);
|
||||
_unassert(0 <= vertex_count && vertex_count <= INT_MAX);
|
||||
for (i = 0; i < edge_count; ++i) {
|
||||
if (i) assert(edges[i - 1][0] <= edges[i][0]);
|
||||
assert(edges[i][0] < vertex_count);
|
||||
assert(edges[i][1] < vertex_count);
|
||||
if (i) _unassert(edges[i - 1][0] <= edges[i][0]);
|
||||
_unassert(edges[i][0] < vertex_count);
|
||||
_unassert(edges[i][1] < vertex_count);
|
||||
}
|
||||
if (!(t = calloc(1, (sizeof(struct Tarjan) +
|
||||
sizeof(struct Vertex) * vertex_count)))) {
|
||||
|
@ -175,7 +175,7 @@ int _tarjan(int vertex_count, const int (*edges)[2], int edge_count,
|
|||
if (out_opt_components) {
|
||||
*out_opt_componentcount = t->Ci;
|
||||
}
|
||||
assert(t->Ri == vertex_count);
|
||||
_unassert(t->Ri == vertex_count);
|
||||
free(t->S.p);
|
||||
free(t);
|
||||
return rc;
|
||||
|
|
|
@ -22,6 +22,6 @@
|
|||
#include "libc/str/str.h"
|
||||
|
||||
dontdiscard void *unhexstr(const char *hexdigs) {
|
||||
assert(strlen(hexdigs) % 2 == 0);
|
||||
_unassert(strlen(hexdigs) % 2 == 0);
|
||||
return unhexbuf(malloc(strlen(hexdigs) / 2), strlen(hexdigs) / 2, hexdigs);
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ int(vasprintf)(char **strp, const char *fmt, va_list va) {
|
|||
if ((p2 = realloc(p, size))) {
|
||||
p = p2;
|
||||
wrote = (vsnprintf)(p, size, fmt, vb);
|
||||
assert(wrote == size - 1);
|
||||
_unassert(wrote == size - 1);
|
||||
rc = wrote;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,10 @@
|
|||
*
|
||||
* This calls functions registered by atexit() before terminating
|
||||
* the current process, and any associated threads. It also calls
|
||||
* all the legacy linker registered destructors in reeverse order
|
||||
* all the legacy linker registered destructors in reversed order
|
||||
*
|
||||
* This implementation allows exit() to be called recursively via
|
||||
* atexit() handlers.
|
||||
*
|
||||
* @param exitcode is masked with 255
|
||||
* @see _Exit()
|
||||
|
|
|
@ -41,9 +41,9 @@ bool __grow(void *pp, size_t *capacity, size_t itemsize, size_t extra) {
|
|||
size_t t1, t2;
|
||||
extra += GUARANTEE_TERMINATOR;
|
||||
p = (void **)pp;
|
||||
assert(itemsize);
|
||||
assert((*p && *capacity) || (!*p && !*capacity));
|
||||
assert(!_isheap(*p) || ((intptr_t)*p & 15) == 0);
|
||||
_unassert(itemsize);
|
||||
_unassert((*p && *capacity) || (!*p && !*capacity));
|
||||
_unassert(!_isheap(*p) || ((intptr_t)*p & 15) == 0);
|
||||
p1 = _isheap(*p) ? *p : NULL;
|
||||
p2 = NULL;
|
||||
n1 = *capacity;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/asancodes.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/bsr.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/likely.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
|
@ -63,6 +64,10 @@
|
|||
#define SHADE(x) (((intptr_t)(x) >> 3) + 0x7fff8000)
|
||||
#define FRAME(x) ((int)((intptr_t)(x) >> 16))
|
||||
|
||||
static unsigned long RoundDownTwoPow(unsigned long x) {
|
||||
return x ? 1ul << _bsrl(x) : 0;
|
||||
}
|
||||
|
||||
static wontreturn void OnUnrecoverableMmapError(const char *s) {
|
||||
if (_weaken(__die)) _weaken(__die)();
|
||||
STRACE("%s %m", s);
|
||||
|
@ -322,7 +327,7 @@ static noasan inline void *Mmap(void *addr, size_t size, int prot, int flags,
|
|||
return VIP(einval());
|
||||
}
|
||||
|
||||
a = max(1, _rounddown2pow(size) >> 16);
|
||||
a = max(1, RoundDownTwoPow(size) >> 16);
|
||||
|
||||
f = (flags & ~MAP_FIXED_NOREPLACE) | MAP_FIXED;
|
||||
if (flags & MAP_FIXED) {
|
||||
|
|
|
@ -91,7 +91,7 @@ void *mremap(void *p, size_t n, size_t m, int f, ... /* void *q */) {
|
|||
size_t i, j, k;
|
||||
struct DirectMap dm;
|
||||
int a, b, prot, flags;
|
||||
assert(!__vforked);
|
||||
_unassert(!__vforked);
|
||||
if (UNLIKELY(!m)) {
|
||||
STRACE("m=0");
|
||||
return VIP(einval());
|
||||
|
|
|
@ -18,10 +18,10 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/sysv/consts/msync.h"
|
||||
|
||||
|
@ -37,7 +37,7 @@
|
|||
*/
|
||||
int msync(void *addr, size_t size, int flags) {
|
||||
int rc;
|
||||
assert(((flags & MS_SYNC) ^ (flags & MS_ASYNC)) || !(MS_SYNC && MS_ASYNC));
|
||||
_unassert(((flags & MS_SYNC) ^ (flags & MS_ASYNC)) || !(MS_SYNC && MS_ASYNC));
|
||||
if (!IsWindows()) {
|
||||
rc = sys_msync(addr, size, flags);
|
||||
} else {
|
||||
|
|
|
@ -95,9 +95,7 @@ static noasan void MunmapImpl(char *p, size_t n) {
|
|||
beg = MAX(_mmi.p[i].x, l);
|
||||
end = _mmi.p[i].y;
|
||||
} else {
|
||||
// shouldn't be possible
|
||||
assert(!"binary search panic");
|
||||
continue;
|
||||
unreachable;
|
||||
}
|
||||
// openbsd even requires that if we mapped, for instance a 5 byte
|
||||
// file, that we be sure to call munmap(file, 5). let's abstract!
|
||||
|
@ -107,8 +105,7 @@ static noasan void MunmapImpl(char *p, size_t n) {
|
|||
q = (char *)a;
|
||||
m = MIN(b, c) - a;
|
||||
if (!IsWindows()) {
|
||||
rc = sys_munmap(q, m);
|
||||
assert(!rc);
|
||||
_npassert(!sys_munmap(q, m));
|
||||
} else {
|
||||
// Handled by UntrackMemoryIntervals() on Windows
|
||||
}
|
||||
|
@ -122,7 +119,7 @@ static noasan int Munmap(char *p, size_t n) {
|
|||
unsigned i;
|
||||
char poison;
|
||||
intptr_t a, b, x, y;
|
||||
assert(!__vforked);
|
||||
_unassert(!__vforked);
|
||||
if (UNLIKELY(!n)) {
|
||||
STRACE("n=0");
|
||||
return einval();
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/promises.internal.h"
|
||||
|
@ -48,30 +49,33 @@ size_t GetStackUsage(char *s, size_t n) {
|
|||
}
|
||||
|
||||
static textexit void LogStackUse(void) {
|
||||
int i, fd;
|
||||
bool quote;
|
||||
char *p, *q;
|
||||
int i, e, fd;
|
||||
size_t n, usage;
|
||||
if (!PLEDGED(STDIO) || !PLEDGED(WPATH) || !PLEDGED(CPATH)) return;
|
||||
usage = GetStackUsage((char *)GetStackAddr(), GetStackSize());
|
||||
fd = open(stacklog, O_APPEND | O_CREAT | O_WRONLY, 0644);
|
||||
p = FormatUint64(stacklog, usage);
|
||||
for (i = 0; i < __argc; ++i) {
|
||||
n = strlen(__argv[i]);
|
||||
if ((q = memchr(__argv[i], '\n', n))) n = q - __argv[i];
|
||||
if (p - stacklog + 1 + 1 + n + 1 + 1 < sizeof(stacklog)) {
|
||||
quote = !!memchr(__argv[i], ' ', n);
|
||||
*p++ = ' ';
|
||||
if (quote) *p++ = '\'';
|
||||
p = mempcpy(p, __argv[i], n);
|
||||
if (quote) *p++ = '\'';
|
||||
} else {
|
||||
break;
|
||||
e = errno;
|
||||
if ((fd = open(stacklog, O_APPEND | O_CREAT | O_WRONLY, 0644)) != -1) {
|
||||
p = FormatUint64(stacklog, usage);
|
||||
for (i = 0; i < __argc; ++i) {
|
||||
n = strlen(__argv[i]);
|
||||
if ((q = memchr(__argv[i], '\n', n))) n = q - __argv[i];
|
||||
if (p - stacklog + 1 + 1 + n + 1 + 1 < sizeof(stacklog)) {
|
||||
quote = !!memchr(__argv[i], ' ', n);
|
||||
*p++ = ' ';
|
||||
if (quote) *p++ = '\'';
|
||||
p = mempcpy(p, __argv[i], n);
|
||||
if (quote) *p++ = '\'';
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*p++ = '\n';
|
||||
write(fd, stacklog, p - stacklog);
|
||||
close(fd);
|
||||
}
|
||||
*p++ = '\n';
|
||||
write(fd, stacklog, p - stacklog);
|
||||
close(fd);
|
||||
errno = e;
|
||||
}
|
||||
|
||||
static textstartup void LogStackUseInit(void) {
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
int UntrackMemoryIntervals(void *addr, size_t size) {
|
||||
int a, b;
|
||||
assert(size > 0);
|
||||
_unassert(size > 0);
|
||||
a = ROUNDDOWN((intptr_t)addr, FRAMESIZE) >> 16;
|
||||
b = ROUNDDOWN((intptr_t)addr + size - 1, FRAMESIZE) >> 16;
|
||||
return ReleaseMemoryIntervals(&_mmi, a, b,
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
textwindows int sys_bind_nt(struct Fd *fd, const void *addr,
|
||||
uint32_t addrsize) {
|
||||
assert(fd->kind == kFdSocket);
|
||||
_npassert(fd->kind == kFdSocket);
|
||||
if (__sys_bind_nt(fd->handle, addr, addrsize) != -1) {
|
||||
return 0;
|
||||
} else {
|
||||
|
|
|
@ -27,7 +27,7 @@ textwindows int sys_connect_nt(struct Fd *fd, const void *addr,
|
|||
uint32_t addrsize) {
|
||||
struct SockFd *sockfd;
|
||||
sockfd = (struct SockFd *)fd->extra;
|
||||
assert(fd->kind == kFdSocket);
|
||||
_npassert(fd->kind == kFdSocket);
|
||||
return __winsockblock(
|
||||
fd->handle, FD_CONNECT_BIT,
|
||||
WSAConnect(fd->handle, addr, addrsize, NULL, NULL, NULL, NULL),
|
||||
|
|
|
@ -378,7 +378,7 @@ static textwindows int afd_poll(int64_t afd_device_handle,
|
|||
struct NtIoStatusBlock *io_status_block) {
|
||||
NtStatus status;
|
||||
/* Blocking operation is not supported.*/
|
||||
assert(io_status_block);
|
||||
_npassert(io_status_block);
|
||||
io_status_block->Status = kNtStatusPending;
|
||||
status =
|
||||
NtDeviceIoControlFile(afd_device_handle, 0, NULL, io_status_block,
|
||||
|
@ -425,11 +425,11 @@ static textwindows void queue__detach_node(struct QueueNode *node) {
|
|||
node->next->prev = node->prev;
|
||||
}
|
||||
|
||||
static textwindows bool queue_is_enqueued(const struct QueueNode *node) {
|
||||
forceinline bool queue_is_enqueued(const struct QueueNode *node) {
|
||||
return node->prev != node;
|
||||
}
|
||||
|
||||
static textwindows bool queue_is_empty(const struct Queue *queue) {
|
||||
forceinline bool queue_is_empty(const struct Queue *queue) {
|
||||
return !queue_is_enqueued(&queue->head);
|
||||
}
|
||||
|
||||
|
@ -558,7 +558,7 @@ static textwindows int ts_tree_add(struct TsTree *ts_tree,
|
|||
}
|
||||
|
||||
static textwindows void port__free(struct PortState *port) {
|
||||
assert(port != NULL);
|
||||
_npassert(port);
|
||||
free(port);
|
||||
}
|
||||
|
||||
|
@ -586,7 +586,7 @@ err1:
|
|||
}
|
||||
|
||||
static textwindows int sock__cancel_poll(struct SockState *sock_state) {
|
||||
assert(sock_state->poll_status == kPollPending);
|
||||
_npassert(sock_state->poll_status == kPollPending);
|
||||
if (afd_cancel_poll(poll_group_get_afd_device_handle(sock_state->poll_group),
|
||||
&sock_state->io_status_block) < 0) {
|
||||
return -1;
|
||||
|
@ -702,13 +702,13 @@ static textwindows void reflock__await_event(void *address) {
|
|||
static textwindows void reflock_ref(struct RefLock *reflock) {
|
||||
long state = InterlockedAdd(&reflock->state, REFLOCK__REF);
|
||||
/* Verify that the counter didn 't overflow and the lock isn' t destroyed.*/
|
||||
assert((state & REFLOCK__DESTROY_MASK) == 0);
|
||||
_npassert((state & REFLOCK__DESTROY_MASK) == 0);
|
||||
}
|
||||
|
||||
static textwindows void reflock_unref(struct RefLock *reflock) {
|
||||
long state = InterlockedAdd(&reflock->state, -REFLOCK__REF);
|
||||
/* Verify that the lock was referenced and not already destroyed.*/
|
||||
assert((state & REFLOCK__DESTROY_MASK & ~REFLOCK__DESTROY) == 0);
|
||||
_npassert((state & REFLOCK__DESTROY_MASK & ~REFLOCK__DESTROY) == 0);
|
||||
if (state == REFLOCK__DESTROY) reflock__signal_event(reflock);
|
||||
}
|
||||
|
||||
|
@ -744,10 +744,10 @@ static textwindows void reflock_unref_and_destroy(struct RefLock *reflock) {
|
|||
state = InterlockedAdd(&reflock->state, REFLOCK__DESTROY - REFLOCK__REF);
|
||||
ref_count = state & REFLOCK__REF_MASK;
|
||||
/* Verify that the lock was referenced and not already destroyed. */
|
||||
assert((state & REFLOCK__DESTROY_MASK) == REFLOCK__DESTROY);
|
||||
_npassert((state & REFLOCK__DESTROY_MASK) == REFLOCK__DESTROY);
|
||||
if (ref_count != 0) reflock__await_event(reflock);
|
||||
state = InterlockedExchange(&reflock->state, REFLOCK__POISON);
|
||||
assert(state == REFLOCK__DESTROY);
|
||||
_npassert(state == REFLOCK__DESTROY);
|
||||
}
|
||||
|
||||
static textwindows void ts_tree_node_unref_and_destroy(
|
||||
|
@ -775,13 +775,13 @@ static textwindows void poll_group_release(struct PollGroup *poll_group) {
|
|||
struct PortState *port_state = poll_group->port_state;
|
||||
struct Queue *poll_group_queue = port_get_poll_group_queue(port_state);
|
||||
poll_group->group_size--;
|
||||
assert(poll_group->group_size < MAX_GROUP_SIZE);
|
||||
_npassert(poll_group->group_size < MAX_GROUP_SIZE);
|
||||
queue_move_to_end(poll_group_queue, &poll_group->queue_node);
|
||||
/* Poll groups are currently only freed when the epoll port is closed. */
|
||||
}
|
||||
|
||||
static textwindows void sock__free(struct SockState *sock_state) {
|
||||
assert(sock_state != NULL);
|
||||
_npassert(sock_state != NULL);
|
||||
free(sock_state);
|
||||
}
|
||||
|
||||
|
@ -827,7 +827,7 @@ static textwindows void sock_force_delete(struct PortState *port_state,
|
|||
}
|
||||
|
||||
static textwindows void poll_group_delete(struct PollGroup *poll_group) {
|
||||
assert(poll_group->group_size == 0);
|
||||
_npassert(poll_group->group_size == 0);
|
||||
CloseHandle(poll_group->afd_device_handle);
|
||||
queue_remove(&poll_group->queue_node);
|
||||
free(poll_group);
|
||||
|
@ -839,7 +839,7 @@ static textwindows int port_delete(struct PortState *port_state) {
|
|||
struct SockState *sock_state;
|
||||
struct PollGroup *poll_group;
|
||||
/* At this point the IOCP port should have been closed.*/
|
||||
assert(!port_state->iocp_handle);
|
||||
_npassert(!port_state->iocp_handle);
|
||||
while ((tree_node = tree_root(&port_state->sock_tree)) != NULL) {
|
||||
sock_state = sock_state_from_tree_node(tree_node);
|
||||
sock_force_delete(port_state, sock_state);
|
||||
|
@ -852,14 +852,14 @@ static textwindows int port_delete(struct PortState *port_state) {
|
|||
poll_group = poll_group_from_queue_node(queue_node);
|
||||
poll_group_delete(poll_group);
|
||||
}
|
||||
assert(queue_is_empty(&port_state->sock_update_queue));
|
||||
_npassert(queue_is_empty(&port_state->sock_update_queue));
|
||||
DeleteCriticalSection(&port_state->lock);
|
||||
port__free(port_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static textwindows int64_t port_get_iocp_handle(struct PortState *port_state) {
|
||||
assert(port_state->iocp_handle);
|
||||
_npassert(port_state->iocp_handle);
|
||||
return port_state->iocp_handle;
|
||||
}
|
||||
|
||||
|
@ -933,7 +933,7 @@ static textwindows uint32_t sock__afd_events_to_epoll_events(uint32_t a) {
|
|||
|
||||
static textwindows int sock_update(struct PortState *port_state,
|
||||
struct SockState *sock_state) {
|
||||
assert(!sock_state->delete_pending);
|
||||
_npassert(!sock_state->delete_pending);
|
||||
if ((sock_state->poll_status == kPollPending) &&
|
||||
!(sock_state->user_events & KNOWN_EVENTS & ~sock_state->pending_events)) {
|
||||
/* All the events the user is interested in are already being
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
textwindows int sys_getpeername_nt(struct Fd *fd, void *out_addr,
|
||||
uint32_t *out_addrsize) {
|
||||
assert(fd->kind == kFdSocket);
|
||||
_npassert(fd->kind == kFdSocket);
|
||||
if (__sys_getpeername_nt(fd->handle, out_addr, out_addrsize) != -1) {
|
||||
return 0;
|
||||
} else {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
textwindows int sys_getsockname_nt(struct Fd *fd, void *out_addr,
|
||||
uint32_t *out_addrsize) {
|
||||
assert(fd->kind == kFdSocket);
|
||||
_npassert(fd->kind == kFdSocket);
|
||||
if (__sys_getsockname_nt(fd->handle, out_addr, out_addrsize) != -1) {
|
||||
return 0;
|
||||
} else {
|
||||
|
|
|
@ -36,7 +36,7 @@ textwindows int sys_getsockopt_nt(struct Fd *fd, int level, int optname,
|
|||
uint32_t in_optlen;
|
||||
struct SockFd *sockfd;
|
||||
struct linger_nt linger;
|
||||
assert(fd->kind == kFdSocket);
|
||||
_npassert(fd->kind == kFdSocket);
|
||||
sockfd = (struct SockFd *)fd->extra;
|
||||
|
||||
if (out_opt_optval && inout_optlen) {
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "libc/sock/syscall_fd.internal.h"
|
||||
|
||||
textwindows int sys_listen_nt(struct Fd *fd, int backlog) {
|
||||
assert(fd->kind == kFdSocket);
|
||||
_npassert(fd->kind == kFdSocket);
|
||||
if (__sys_listen_nt(fd->handle, backlog) != -1) {
|
||||
return 0;
|
||||
} else {
|
||||
|
|
|
@ -274,6 +274,11 @@ static int WaitForTrace(int main) {
|
|||
|
||||
/**
|
||||
* Disables internet access.
|
||||
*
|
||||
* Warning: This function uses ptrace to react to seccomp filter events.
|
||||
* This approach is effective, but it's not bulletproof, since a highly
|
||||
* motivated attacker could theoretically use threads to modify sockaddr
|
||||
* in the short time between it being monitored and the actual syscall.
|
||||
*/
|
||||
int nointernet(void) {
|
||||
int ws, act, main;
|
||||
|
@ -317,7 +322,7 @@ int nointernet(void) {
|
|||
sigprocmask(SIG_SETMASK, &old, 0);
|
||||
return eperm();
|
||||
}
|
||||
assert(WIFSTOPPED(ws));
|
||||
_npassert(WIFSTOPPED(ws));
|
||||
|
||||
// parent process becomes monitor of subprocess tree. all signals
|
||||
// continue to be blocked since we assume they'll also be sent to
|
||||
|
|
|
@ -53,7 +53,7 @@ ssize_t appendd(char **b, const void *s, size_t l) {
|
|||
z.n = ROUNDUP(z.n, W);
|
||||
if ((p = realloc(p, z.n))) {
|
||||
z.n = malloc_usable_size(p);
|
||||
assert(!(z.n & (W - 1)));
|
||||
_unassert(!(z.n & (W - 1)));
|
||||
*b = p;
|
||||
} else {
|
||||
return -1;
|
||||
|
|
|
@ -51,14 +51,14 @@ ssize_t appendr(char **b, size_t i) {
|
|||
char *p;
|
||||
size_t n;
|
||||
struct appendz z;
|
||||
assert(b);
|
||||
_unassert(b);
|
||||
z = appendz((p = *b));
|
||||
if (i != z.i || !p) {
|
||||
n = ROUNDUP(i + 1, 8) + W;
|
||||
if (n > z.n || _bsrl(n) < _bsrl(z.n)) {
|
||||
if ((p = realloc(p, n))) {
|
||||
z.n = malloc_usable_size(p);
|
||||
assert(!(z.n & (W - 1)));
|
||||
_unassert(!(z.n & (W - 1)));
|
||||
*b = p;
|
||||
} else {
|
||||
return -1;
|
||||
|
|
|
@ -67,7 +67,7 @@ ssize_t appendw(char **b, uint64_t w) {
|
|||
z.n = ROUNDUP(z.n, W);
|
||||
if ((p = realloc(p, z.n))) {
|
||||
z.n = malloc_usable_size(p);
|
||||
assert(!(z.n & (W - 1)));
|
||||
_unassert(!(z.n & (W - 1)));
|
||||
*b = p;
|
||||
} else {
|
||||
return -1;
|
||||
|
|
|
@ -34,7 +34,7 @@ struct appendz appendz(char *p) {
|
|||
struct appendz z;
|
||||
if (p) {
|
||||
z.n = malloc_usable_size(p);
|
||||
assert(z.n >= W * 2 && !(z.n & (W - 1)));
|
||||
_unassert(z.n >= W * 2 && !(z.n & (W - 1)));
|
||||
z.i = *(size_t *)(p + z.n - W);
|
||||
if (!IsTiny() && W == 8) {
|
||||
/*
|
||||
|
@ -43,10 +43,10 @@ struct appendz appendz(char *p) {
|
|||
* can be free()'d safely, but they need to be allocated by the
|
||||
* append library, because we write a special value to the end.
|
||||
*/
|
||||
assert((z.i >> 48) == APPEND_COOKIE);
|
||||
_unassert((z.i >> 48) == APPEND_COOKIE);
|
||||
z.i &= 0x0000ffffffffffff;
|
||||
}
|
||||
assert(z.n >= z.i);
|
||||
_unassert(z.n >= z.i);
|
||||
} else {
|
||||
z.i = 0;
|
||||
z.n = 0;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "libc/stdio/stdio.h"
|
||||
|
||||
/**
|
||||
* Clears error state on stream.
|
||||
* Clears eof and error state indicators on stream.
|
||||
*
|
||||
* @param f is file object stream pointer
|
||||
* @see clearerr_unlocked()
|
||||
|
|
|
@ -18,6 +18,13 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
/**
|
||||
* Clears eof and error state indicators on stream.
|
||||
*
|
||||
* @param f is file object stream pointer
|
||||
* @see clearerr()
|
||||
* @threadsafe
|
||||
*/
|
||||
void clearerr_unlocked(FILE *f) {
|
||||
f->state = 0;
|
||||
}
|
||||
|
|
|
@ -336,7 +336,8 @@ static struct dirent *readdir_impl(DIR *dir) {
|
|||
ent = 0;
|
||||
zip = _weaken(__zipos_get)();
|
||||
while (!ent && dir->tell < dir->zip.records) {
|
||||
assert(ZIP_CFILE_MAGIC(zip->map + dir->zip.offset) == kZipCfileHdrMagic);
|
||||
_npassert(ZIP_CFILE_MAGIC(zip->map + dir->zip.offset) ==
|
||||
kZipCfileHdrMagic);
|
||||
s = ZIP_CFILE_NAME(zip->map + dir->zip.offset);
|
||||
n = ZIP_CFILE_NAMESIZE(zip->map + dir->zip.offset);
|
||||
if (dir->zip.prefixlen < n &&
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/stdio/lock.internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
|
@ -31,6 +33,8 @@ size_t fread(void *buf, size_t stride, size_t count, FILE *f) {
|
|||
size_t rc;
|
||||
flockfile(f);
|
||||
rc = fread_unlocked(buf, stride, count, f);
|
||||
STDIOTRACE("fread(%p, %'zu, %'zu, %p) → %'zu %s", buf, stride, count, f, rc,
|
||||
DescribeStdioState(f->state));
|
||||
funlockfile(f);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,9 @@ size_t fread_unlocked(void *buf, size_t stride, size_t count, FILE *f) {
|
|||
ssize_t rc;
|
||||
size_t n, m;
|
||||
struct iovec iov[2];
|
||||
if (f->state) {
|
||||
return 0;
|
||||
}
|
||||
if ((f->iomode & O_ACCMODE) == O_WRONLY) {
|
||||
f->state = errno = EBADF;
|
||||
return 0;
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/stdio/lock.internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
|
@ -37,6 +39,8 @@ int fseeko(FILE *f, int64_t offset, int whence) {
|
|||
int rc;
|
||||
flockfile(f);
|
||||
rc = fseeko_unlocked(f, offset, whence);
|
||||
STDIOTRACE("fseeko(%p, %'ld, %s) → %d %s", f, offset, DescribeWhence(whence),
|
||||
rc, DescribeStdioState(f->state));
|
||||
funlockfile(f);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ int fseeko_unlocked(FILE *f, int64_t offset, int whence) {
|
|||
if (lseek(f->fd, offset, whence) != -1) {
|
||||
f->beg = 0;
|
||||
f->end = 0;
|
||||
f->state = 0;
|
||||
res = 0;
|
||||
} else {
|
||||
f->state = errno == ESPIPE ? EBADF : errno;
|
||||
|
@ -69,6 +70,7 @@ int fseeko_unlocked(FILE *f, int64_t offset, int whence) {
|
|||
}
|
||||
if (0 <= pos && pos <= f->end) {
|
||||
f->beg = pos;
|
||||
f->state = 0;
|
||||
res = 0;
|
||||
} else {
|
||||
f->state = errno = EINVAL;
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/stdio/lock.internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
|
@ -31,6 +33,8 @@ size_t fwrite(const void *data, size_t stride, size_t count, FILE *f) {
|
|||
size_t rc;
|
||||
flockfile(f);
|
||||
rc = fwrite_unlocked(data, stride, count, f);
|
||||
STDIOTRACE("fwrite(%p, %'zu, %'zu, %p) → %'zu %s", data, stride, count, f, rc,
|
||||
DescribeStdioState(f->state));
|
||||
funlockfile(f);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -44,6 +44,9 @@ size_t fwrite_unlocked(const void *data, size_t stride, size_t count, FILE *f) {
|
|||
size_t n, m;
|
||||
const char *p;
|
||||
struct iovec iov[2];
|
||||
if (f->state) {
|
||||
return 0;
|
||||
}
|
||||
if ((f->iomode & O_ACCMODE) == O_RDONLY) {
|
||||
f->state = errno = EBADF;
|
||||
return 0;
|
||||
|
|
|
@ -51,9 +51,9 @@ ssize_t kvappendf(char **b, const char *f, va_list v) {
|
|||
z.n = ROUNDUP(z.n, W);
|
||||
if ((p = realloc(p, z.n))) {
|
||||
z.n = malloc_usable_size(p);
|
||||
assert(!(z.n & (W - 1)));
|
||||
_unassert(!(z.n & (W - 1)));
|
||||
s = kvsnprintf(p + z.i, z.n - W - z.i, f, w);
|
||||
assert(s == r);
|
||||
_unassert(s == r);
|
||||
*b = p;
|
||||
} else {
|
||||
va_end(w);
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/lcg.internal.h"
|
||||
#include "libc/stdio/rand.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/temp.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
@ -38,7 +38,7 @@ int mkostempsmi(char *tpl, int slen, unsigned flags, uint64_t *rando, int mode,
|
|||
size_t wildlen = strlen(WILDCARD);
|
||||
if (len < wildlen || slen > len - wildlen) return einval();
|
||||
char *ss = tpl + len - wildlen - slen;
|
||||
assert(memcmp(ss, WILDCARD, wildlen) == 0);
|
||||
_npassert(memcmp(ss, WILDCARD, wildlen) == 0);
|
||||
flags = (flags & ~(flags & O_ACCMODE)) | O_RDWR | O_CREAT | O_EXCL;
|
||||
unsigned attempts = ATTEMPTS;
|
||||
do {
|
||||
|
|
|
@ -31,7 +31,6 @@ int pclose(FILE *f) {
|
|||
int ws, pid;
|
||||
pid = f->pid;
|
||||
fclose(f);
|
||||
assert(pid);
|
||||
if (!pid) return 0;
|
||||
TryAgain:
|
||||
if (wait4(pid, &ws, 0, 0) != -1) {
|
||||
|
|
|
@ -44,9 +44,9 @@ ssize_t(vappendf)(char **b, const char *f, va_list v) {
|
|||
z.n = ROUNDUP(z.n, W);
|
||||
if ((p = realloc(p, z.n))) {
|
||||
z.n = malloc_usable_size(p);
|
||||
assert(!(z.n & (W - 1)));
|
||||
_unassert(!(z.n & (W - 1)));
|
||||
s = (vsnprintf)(p + z.i, z.n - W - z.i, f, w);
|
||||
assert(s == r);
|
||||
_unassert(s == r);
|
||||
*b = p;
|
||||
} else {
|
||||
va_end(w);
|
||||
|
|
|
@ -126,7 +126,7 @@ int BLAKE2B256_Update(struct Blake2b *b2b, const void *in_data, size_t len) {
|
|||
return 0;
|
||||
}
|
||||
// More input remains therefore we must have filled |b2b->block|.
|
||||
assert(b2b->block_used == BLAKE2B_CBLOCK);
|
||||
_unassert(b2b->block_used == BLAKE2B_CBLOCK);
|
||||
Blake2bTransform(b2b, b2b->block.words, BLAKE2B_CBLOCK,
|
||||
/*is_final_block=*/0);
|
||||
b2b->block_used = 0;
|
||||
|
|
|
@ -51,7 +51,7 @@ static unsigned _getcachesize_cpuid4(int type, int level) {
|
|||
* @return size in bytes, or 0 if unknown
|
||||
*/
|
||||
unsigned _getcachesize(int type, int level) {
|
||||
assert(1 <= type && type <= 3);
|
||||
assert(level >= 1);
|
||||
_unassert(1 <= type && type <= 3);
|
||||
_unassert(level >= 1);
|
||||
return _getcachesize_cpuid4(type, level);
|
||||
}
|
||||
|
|
|
@ -70,6 +70,6 @@ char *strchr(const char *s, int c) {
|
|||
} else {
|
||||
r = strchr_pure(s, c);
|
||||
}
|
||||
assert(!r || *r || !(c & 255));
|
||||
_unassert(!r || *r || !(c & 255));
|
||||
return (char *)r;
|
||||
}
|
||||
|
|
|
@ -68,6 +68,6 @@ char *strchrnul(const char *s, int c) {
|
|||
} else {
|
||||
r = strchrnul_pure(s, c);
|
||||
}
|
||||
assert((*r & 255) == (c & 255) || !*r);
|
||||
_unassert((*r & 255) == (c & 255) || !*r);
|
||||
return (char *)r;
|
||||
}
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
static noasan size_t strnlen_x64(const char *s, size_t n, size_t i) {
|
||||
|
@ -52,7 +52,7 @@ noasan size_t strnlen(const char *s, size_t n) {
|
|||
for (;; ++i) {
|
||||
if (i == n || !s[i]) break;
|
||||
}
|
||||
assert(i == n || (i < n && !s[i]));
|
||||
_unassert(i == n || (i < n && !s[i]));
|
||||
if (IsAsan()) __asan_verify(s, i);
|
||||
return i;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,6 @@ noasan size_t strnlen16(const char16_t *s, size_t n) {
|
|||
for (i = 0;; ++i) {
|
||||
if (i == n || !s[i]) break;
|
||||
}
|
||||
assert(i == n || (i < n && !s[i]));
|
||||
_unassert(i == n || (i < n && !s[i]));
|
||||
return i;
|
||||
}
|
||||
|
|
|
@ -56,6 +56,6 @@ noasan size_t strnlen_s(const char *s, size_t n) {
|
|||
for (;; ++i) {
|
||||
if (i == n || !s[i]) break;
|
||||
}
|
||||
assert(i == n || (i < n && !s[i]));
|
||||
_unassert(i == n || (i < n && !s[i]));
|
||||
return i;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,6 @@
|
|||
* @note if dest is NULL, count has to be zero
|
||||
*/
|
||||
size_t strxfrm(char *dest, const char *src, size_t count) {
|
||||
assert(dest == NULL ? count == 0 : 1);
|
||||
_unassert(dest == NULL ? count == 0 : 1);
|
||||
return strlcpy(dest, src, count);
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ static void CheckSignalHandler(int sig) {
|
|||
#if 0
|
||||
int i;
|
||||
struct sigaction sa = {0};
|
||||
assert(0 <= sig - 1 && sig - 1 < ARRAYLEN(wanthandlers));
|
||||
_unassert(0 <= sig - 1 && sig - 1 < ARRAYLEN(wanthandlers));
|
||||
CHECK_EQ(0, sigaction(sig, 0, &sa));
|
||||
CHECK_EQ(0, memcmp(wanthandlers + sig - 1, &sa, sizeof(sa)),
|
||||
"signal handler for %s was %p/%#x/%#x:%x "
|
||||
|
|
|
@ -47,7 +47,6 @@ errno_t pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched) {
|
|||
attr->__inheritsched = inheritsched;
|
||||
return 0;
|
||||
default:
|
||||
assert(!"badval");
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ static int rmrfdir(const char *dirpath) {
|
|||
while ((e = readdir(d))) {
|
||||
if (!strcmp(e->d_name, ".")) continue;
|
||||
if (!strcmp(e->d_name, "..")) continue;
|
||||
assert(!strchr(e->d_name, '/'));
|
||||
_npassert(!strchr(e->d_name, '/'));
|
||||
path = xjoinpaths(dirpath, e->d_name);
|
||||
if (e->d_type == DT_DIR) {
|
||||
rc = rmrfdir(path);
|
||||
|
|
|
@ -47,7 +47,7 @@ void *xloadzd(bool *o, void **t, const void *p, size_t n, size_t m, size_t c,
|
|||
z_stream zs;
|
||||
char *q, *b;
|
||||
int64_t x, y;
|
||||
assert(z == 2 || z == 4);
|
||||
_unassert(z == 2 || z == 4);
|
||||
b = q = malloc(m);
|
||||
__inflate(q, m, p, n);
|
||||
r = memalign(z, c * z);
|
||||
|
@ -61,7 +61,7 @@ void *xloadzd(bool *o, void **t, const void *p, size_t n, size_t m, size_t c,
|
|||
}
|
||||
}
|
||||
free(q);
|
||||
assert(crc32_z(0, r, c * z) == s);
|
||||
_npassert(crc32_z(0, r, c * z) == s);
|
||||
if (_lockcmpxchg(t, 0, r)) {
|
||||
__cxa_atexit(free, r, 0);
|
||||
} else {
|
||||
|
|
|
@ -34,7 +34,7 @@ ssize_t __zipos_find(struct Zipos *zipos, const struct ZiposUri *name) {
|
|||
c = GetZipCdirOffset(zipos->cdir);
|
||||
n = GetZipCdirRecords(zipos->cdir);
|
||||
for (i = 0; i < n; ++i, c += ZIP_CFILE_HDRSIZE(zipos->map + c)) {
|
||||
assert(ZIP_CFILE_MAGIC(zipos->map + c) == kZipCfileHdrMagic);
|
||||
_npassert(ZIP_CFILE_MAGIC(zipos->map + c) == kZipCfileHdrMagic);
|
||||
zname = ZIP_CFILE_NAME(zipos->map + c);
|
||||
znamesize = ZIP_CFILE_NAMESIZE(zipos->map + c);
|
||||
if ((name->len == znamesize && !memcmp(name->path, zname, name->len)) ||
|
||||
|
|
|
@ -49,7 +49,7 @@ static size_t maptotal;
|
|||
static void *__zipos_mmap(size_t mapsize) {
|
||||
char *start;
|
||||
size_t offset;
|
||||
assert(mapsize);
|
||||
_unassert(mapsize);
|
||||
offset = maptotal;
|
||||
maptotal += mapsize;
|
||||
start = (char *)kMemtrackZiposStart;
|
||||
|
@ -131,7 +131,7 @@ static int __zipos_load(struct Zipos *zipos, size_t cf, unsigned flags,
|
|||
int rc, fd, minfd;
|
||||
struct ZiposHandle *h;
|
||||
lf = GetZipCfileOffset(zipos->map + cf);
|
||||
assert((ZIP_LFILE_MAGIC(zipos->map + lf) == kZipLfileHdrMagic));
|
||||
_npassert((ZIP_LFILE_MAGIC(zipos->map + lf) == kZipLfileHdrMagic));
|
||||
size = GetZipLfileUncompressedSize(zipos->map + lf);
|
||||
switch (ZIP_LFILE_COMPRESSIONMETHOD(zipos->map + lf)) {
|
||||
case kZipCompressionNone:
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
bool HeaderHas(struct HttpMessage *m, const char *b, int h, const char *s,
|
||||
size_t n) {
|
||||
size_t i;
|
||||
assert(0 <= h && h < kHttpHeadersMax);
|
||||
_unassert(0 <= h && h < kHttpHeadersMax);
|
||||
if (n == -1) n = s ? strlen(s) : 0;
|
||||
if (m->headers[h].a) {
|
||||
if (memmem(b + m->headers[h].a, m->headers[h].b - m->headers[h].a, s, n)) {
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
* Initializes HTTP message parser.
|
||||
*/
|
||||
void InitHttpMessage(struct HttpMessage *r, int type) {
|
||||
assert(type == kHttpRequest || type == kHttpResponse);
|
||||
_unassert(type == kHttpRequest || type == kHttpResponse);
|
||||
bzero(r, sizeof(*r));
|
||||
r->type = type;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,22 @@
|
|||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
char testlib_enable_tmp_setup_teardown;
|
||||
|
||||
TEST(read, eof) {
|
||||
char b[8] = "hello";
|
||||
ASSERT_SYS(0, 3, creat("foo", 0644));
|
||||
ASSERT_SYS(0, 4, open("foo", O_RDONLY));
|
||||
ASSERT_SYS(0, 0, read(4, b, 8));
|
||||
ASSERT_SYS(0, 8, write(3, b, 8));
|
||||
ASSERT_SYS(0, 8, read(4, b, 8));
|
||||
ASSERT_SYS(0, 0, read(4, b, 8));
|
||||
ASSERT_SYS(0, 0, close(4));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static long Read(long fd, void *buf, unsigned long size) {
|
||||
long ax, di, si, dx;
|
||||
asm volatile("syscall"
|
||||
|
|
|
@ -120,6 +120,9 @@ o/$(MODE)/test/libc/calls/lock_test.com.runs: \
|
|||
o/$(MODE)/test/libc/calls/openbsd_test.com.runs: \
|
||||
private .PLEDGE = stdio rpath wpath cpath fattr proc unveil
|
||||
|
||||
o/$(MODE)/test/libc/calls/read_test.com.runs: \
|
||||
private .UNVEIL += /dev/zero
|
||||
|
||||
# TODO(jart): Update nointernet() to allow AF_INET6
|
||||
o/$(MODE)/test/libc/calls/pledge_test.com.runs: \
|
||||
private .INTERNET = 1
|
||||
|
|
62
test/libc/runtime/exit_test.c
Normal file
62
test/libc/runtime/exit_test.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/testlib/subprocess.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
int i, *p;
|
||||
|
||||
void SetUp(void) {
|
||||
p = _mapshared(FRAMESIZE);
|
||||
}
|
||||
|
||||
void TearDown(void) {
|
||||
munmap(p, FRAMESIZE);
|
||||
}
|
||||
|
||||
void AtExit3(void) {
|
||||
p[i++] = 3;
|
||||
}
|
||||
|
||||
void AtExit2(void) {
|
||||
p[i++] = 2;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
void AtExit1(void) {
|
||||
p[i++] = 1;
|
||||
atexit(AtExit2);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// consistent with glibc, musl, freebsd, openbsd & netbsd
|
||||
// please note posix says recursion is undefined behavior
|
||||
// however, fifo ordering of atexit handlers is specified
|
||||
TEST(exit, test) {
|
||||
SPAWN(fork);
|
||||
atexit(AtExit3);
|
||||
atexit(AtExit3);
|
||||
atexit(AtExit1);
|
||||
exit(0);
|
||||
EXITS(2);
|
||||
ASSERT_EQ(1, p[0]);
|
||||
ASSERT_EQ(2, p[1]);
|
||||
ASSERT_EQ(3, p[2]);
|
||||
ASSERT_EQ(3, p[3]);
|
||||
}
|
60
test/libc/stdio/fread_test.c
Normal file
60
test/libc/stdio/fread_test.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
char testlib_enable_tmp_setup_teardown;
|
||||
|
||||
TEST(fread, eofIsSticky) {
|
||||
FILE *fo, *fi;
|
||||
char b[10] = "hello";
|
||||
ASSERT_NE(NULL, (fo = fopen("foo", "w")));
|
||||
ASSERT_NE(NULL, (fi = fopen("foo", "r")));
|
||||
ASSERT_EQ(0, fread(b, 1, 8, fi));
|
||||
ASSERT_TRUE(feof(fi));
|
||||
ASSERT_EQ(8, fwrite(b, 1, 8, fo));
|
||||
ASSERT_EQ(0, fflush(fo));
|
||||
ASSERT_EQ(0, fread(b, 1, 8, fi));
|
||||
ASSERT_TRUE(feof(fi));
|
||||
clearerr(fi);
|
||||
ASSERT_EQ(8, fread(b, 1, 10, fi));
|
||||
ASSERT_TRUE(feof(fi));
|
||||
ASSERT_EQ(0, fseek(fi, 0, SEEK_SET));
|
||||
ASSERT_FALSE(feof(fi));
|
||||
ASSERT_EQ(0, fclose(fi));
|
||||
ASSERT_EQ(0, fclose(fo));
|
||||
}
|
||||
|
||||
TEST(fread, seekWithBuffer) {
|
||||
FILE *f;
|
||||
char b[8] = "hellosup";
|
||||
char c[8] = {0};
|
||||
char d[8] = {0};
|
||||
ASSERT_NE(NULL, (f = fopen("foo", "w")));
|
||||
ASSERT_EQ(8, fwrite(b, 1, 8, f));
|
||||
ASSERT_EQ(0, fclose(f));
|
||||
ASSERT_NE(NULL, (f = fopen("foo", "r")));
|
||||
ASSERT_EQ(5, fread(c, 1, 5, f));
|
||||
ASSERT_STREQ("hello", c);
|
||||
ASSERT_EQ(0, fseek(f, 1, SEEK_SET));
|
||||
ASSERT_EQ(5, fread(d, 1, 5, f));
|
||||
ASSERT_STREQ("ellos", d);
|
||||
ASSERT_EQ(0, fclose(f));
|
||||
}
|
|
@ -20,10 +20,10 @@
|
|||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdio/rand.h"
|
||||
#include "libc/mem/gc.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/rand.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
|
@ -39,6 +39,10 @@ char testlib_enable_tmp_setup_teardown;
|
|||
TEST(fwrite, test) {
|
||||
ASSERT_NE(NULL, (f = fopen(PATH, "wb")));
|
||||
EXPECT_EQ(-1, fgetc(f));
|
||||
ASSERT_FALSE(feof(f));
|
||||
ASSERT_EQ(EBADF, errno);
|
||||
ASSERT_EQ(EBADF, ferror(f));
|
||||
clearerr(f);
|
||||
EXPECT_EQ(5, fwrite("hello", 1, 5, f));
|
||||
EXPECT_EQ(5, ftell(f));
|
||||
EXPECT_NE(-1, fclose(f));
|
||||
|
@ -60,6 +64,7 @@ TEST(fwrite, testSmallBuffer) {
|
|||
ASSERT_NE(NULL, (f = fopen(PATH, "wb")));
|
||||
setbuffer(f, gc(malloc(1)), 1);
|
||||
EXPECT_EQ(-1, fgetc(f));
|
||||
clearerr(f);
|
||||
EXPECT_EQ(5, fwrite("hello", 1, 5, f));
|
||||
EXPECT_EQ(5, ftell(f));
|
||||
EXPECT_NE(-1, fclose(f));
|
||||
|
@ -84,6 +89,7 @@ TEST(fwrite, testLineBuffer) {
|
|||
ASSERT_NE(NULL, (f = fopen(PATH, "wb")));
|
||||
setvbuf(f, NULL, _IOLBF, 64);
|
||||
EXPECT_EQ(-1, fgetc(f));
|
||||
clearerr(f);
|
||||
EXPECT_EQ(5, fwrite("heyy\n", 1, 5, f));
|
||||
EXPECT_EQ(0, fread(buf, 0, 0, f));
|
||||
EXPECT_FALSE(feof(f));
|
||||
|
@ -112,6 +118,7 @@ TEST(fwrite, testNoBuffer) {
|
|||
ASSERT_NE(NULL, (f = fopen(PATH, "wb")));
|
||||
setvbuf(f, NULL, _IONBF, 64);
|
||||
EXPECT_EQ(-1, fgetc(f));
|
||||
clearerr(f);
|
||||
EXPECT_EQ(5, fwrite("heyy\n", 1, 5, f));
|
||||
EXPECT_EQ(5, ftell(f));
|
||||
EXPECT_NE(-1, fclose(f));
|
||||
|
|
5
third_party/dlmalloc/dlmalloc.c
vendored
5
third_party/dlmalloc/dlmalloc.c
vendored
|
@ -28,17 +28,20 @@
|
|||
#define USE_LOCKS 2
|
||||
#define MORECORE_CONTIGUOUS 0
|
||||
#define MALLOC_INSPECT_ALL 1
|
||||
#define ABORT_ON_ASSERT_FAILURE 0
|
||||
|
||||
#if IsTiny()
|
||||
#define INSECURE 1
|
||||
#define PROCEED_ON_ERROR 1
|
||||
#define ABORT_ON_ASSERT_FAILURE 0
|
||||
#endif
|
||||
|
||||
#if IsModeDbg()
|
||||
#define DEBUG 1
|
||||
#endif
|
||||
|
||||
#undef assert
|
||||
#define assert(x) _npassert(x)
|
||||
|
||||
#include "third_party/dlmalloc/platform.inc"
|
||||
#include "third_party/dlmalloc/locks.inc"
|
||||
#include "third_party/dlmalloc/chunks.inc"
|
||||
|
|
4
third_party/dlmalloc/platform.inc
vendored
4
third_party/dlmalloc/platform.inc
vendored
|
@ -200,10 +200,6 @@
|
|||
#endif /* LACKS_ERRNO_H */
|
||||
#ifdef DEBUG
|
||||
#if ABORT_ON_ASSERT_FAILURE
|
||||
#undef assert
|
||||
#define assert(x) if(!(x)) ABORT
|
||||
#else /* ABORT_ON_ASSERT_FAILURE */
|
||||
#include <assert.h>
|
||||
#endif /* ABORT_ON_ASSERT_FAILURE */
|
||||
#else /* DEBUG */
|
||||
#ifndef assert
|
||||
|
|
4
third_party/double-conversion/README.cosmo
vendored
4
third_party/double-conversion/README.cosmo
vendored
|
@ -11,3 +11,7 @@ ORIGIN
|
|||
LICENSE
|
||||
|
||||
BSD 3-Clause License
|
||||
|
||||
LOCAL CHANGES
|
||||
|
||||
- Use _unassert() macro for undefined behavior on failed assertions
|
||||
|
|
|
@ -28,6 +28,8 @@ THIRD_PARTY_DOUBLECONVERSION_TEST_BINS = \
|
|||
$(THIRD_PARTY_DOUBLECONVERSION_TEST_COMS) \
|
||||
$(THIRD_PARTY_DOUBLECONVERSION_TEST_COMS:%=%.dbg)
|
||||
|
||||
THIRD_PARTY_DOUBLECONVERSION_ARTIFACTS += THIRD_PARTY_DOUBLECONVERSION_TEST_A
|
||||
|
||||
THIRD_PARTY_DOUBLECONVERSION_TEST_A_SRCS_CC = \
|
||||
third_party/double-conversion/test/cctest.cc \
|
||||
third_party/double-conversion/test/gay-fixed.cc \
|
||||
|
@ -52,6 +54,10 @@ THIRD_PARTY_DOUBLECONVERSION_TEST_A_HDRS = \
|
|||
third_party/double-conversion/test/gay-shortest.h \
|
||||
third_party/double-conversion/test/gay-shortest-single.h
|
||||
|
||||
THIRD_PARTY_DOUBLECONVERSION_TEST_A_SRCS = \
|
||||
$(THIRD_PARTY_DOUBLECONVERSION_TEST_A_SRCS_C) \
|
||||
$(THIRD_PARTY_DOUBLECONVERSION_TEST_A_SRCS_CC)
|
||||
|
||||
THIRD_PARTY_DOUBLECONVERSION_A_OBJS = \
|
||||
$(THIRD_PARTY_DOUBLECONVERSION_A_SRCS_C:%.c=o/$(MODE)/%.o) \
|
||||
$(THIRD_PARTY_DOUBLECONVERSION_A_SRCS_CC:%.cc=o/$(MODE)/%.o)
|
||||
|
|
3
third_party/double-conversion/test/cctest.cc
vendored
3
third_party/double-conversion/test/cctest.cc
vendored
|
@ -24,9 +24,6 @@
|
|||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "libc/isystem/stdio.h"
|
||||
#include "libc/isystem/stdlib.h"
|
||||
#include "libc/isystem/string.h"
|
||||
#include "third_party/double-conversion/test/cctest.h"
|
||||
// clang-format off
|
||||
|
||||
|
|
2
third_party/double-conversion/test/cctest.h
vendored
2
third_party/double-conversion/test/cctest.h
vendored
|
@ -26,8 +26,6 @@
|
|||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef CCTEST_H_
|
||||
#define CCTEST_H_
|
||||
#include "libc/isystem/stdio.h"
|
||||
#include "libc/isystem/string.h"
|
||||
#include "third_party/double-conversion/utils.h"
|
||||
// clang-format off
|
||||
|
||||
|
|
1
third_party/double-conversion/test/checks.h
vendored
1
third_party/double-conversion/test/checks.h
vendored
|
@ -26,7 +26,6 @@
|
|||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef V8_CHECKS_H_
|
||||
#define V8_CHECKS_H_
|
||||
#include "libc/isystem/string.h"
|
||||
#include "third_party/double-conversion/test/flags.h"
|
||||
// clang-format off
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "libc/isystem/stdlib.h"
|
||||
#include "third_party/double-conversion/bignum-dtoa.h"
|
||||
#include "third_party/double-conversion/ieee.h"
|
||||
#include "third_party/double-conversion/test/cctest.h"
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "libc/isystem/stdlib.h"
|
||||
#include "libc/isystem/string.h"
|
||||
#include "third_party/double-conversion/bignum.h"
|
||||
#include "third_party/double-conversion/test/cctest.h"
|
||||
#include "third_party/double-conversion/utils.h"
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "libc/isystem/string.h"
|
||||
#include "third_party/double-conversion/double-conversion.h"
|
||||
#include "third_party/double-conversion/ieee.h"
|
||||
#include "third_party/double-conversion/test/cctest.h"
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "libc/isystem/stdlib.h"
|
||||
#include "third_party/double-conversion/diy-fp.h"
|
||||
#include "third_party/double-conversion/test/cctest.h"
|
||||
#include "third_party/double-conversion/utils.h"
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "libc/isystem/stdlib.h"
|
||||
#include "third_party/double-conversion/double-conversion.h"
|
||||
#include "third_party/double-conversion/ieee.h"
|
||||
#include "third_party/double-conversion/test/cctest.h"
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "libc/isystem/stdlib.h"
|
||||
#include "third_party/double-conversion/diy-fp.h"
|
||||
#include "third_party/double-conversion/fast-dtoa.h"
|
||||
#include "third_party/double-conversion/ieee.h"
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "libc/isystem/stdlib.h"
|
||||
#include "third_party/double-conversion/fixed-dtoa.h"
|
||||
#include "third_party/double-conversion/ieee.h"
|
||||
#include "third_party/double-conversion/test/cctest.h"
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "libc/isystem/stdlib.h"
|
||||
#include "third_party/double-conversion/diy-fp.h"
|
||||
#include "third_party/double-conversion/ieee.h"
|
||||
#include "third_party/double-conversion/test/cctest.h"
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "libc/isystem/stdlib.h"
|
||||
#include "third_party/double-conversion/bignum.h"
|
||||
#include "third_party/double-conversion/diy-fp.h"
|
||||
#include "third_party/double-conversion/ieee.h"
|
||||
|
|
4
third_party/double-conversion/utils.h
vendored
4
third_party/double-conversion/utils.h
vendored
|
@ -9,7 +9,11 @@
|
|||
#include "third_party/libcxx/cstring"
|
||||
// clang-format off
|
||||
|
||||
// [jart] use undefined behaavior to make code tinier
|
||||
// use ubsan build mode to troubleshoot errors
|
||||
#define DOUBLE_CONVERSION_ASSERT(x) _unassert(x)
|
||||
#define DOUBLE_CONVERSION_UNREACHABLE() unreachable
|
||||
#define DOUBLE_CONVERSION_UNIMPLEMENTED() notpossible
|
||||
|
||||
// Use DOUBLE_CONVERSION_NON_PREFIXED_MACROS to get unprefixed macros as was
|
||||
// the case in double-conversion releases prior to 3.1.6
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue