From 1ff9ab95acf0b97294dae635ad8f90a17439c697 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Mon, 1 Feb 2021 03:33:13 -0800 Subject: [PATCH] Make C memory safe like Rust This change enables Address Sanitizer systemically w/ `make MODE=dbg`. Our version of Rust's `unsafe` keyword is named `noasan` which is used for two functions that do aligned memory chunking, like `strcpy.c` and we need to fix the tiny DEFLATE code, but that's it everything else is fabulous you can have all the fischer price security blankets you need Best of all is we're now able to use the ASAN data in Blinkenlights to colorize the memory dumps. See the screenshot below of a test program: https://justine.lol/blinkenlights/asan.png Which is operating on float arrays stored on the stack, with red areas indicating poisoned memory, and the green areas indicate valid memory. --- ape/lib/apelib.mk | 7 +- build/compile | 3 + build/config.mk | 4 +- build/definitions.mk | 5 +- build/mkdeps | 8 +- dsp/core/core.mk | 7 +- dsp/tty/hidecursor.c | 2 +- dsp/tty/tty.mk | 6 - dsp/tty/windex.S | 2 +- examples/crashreport.c | 6 +- examples/examples.mk | 1 - libc/calls/chdir.c | 2 - libc/calls/creat.c | 3 +- libc/calls/dup3.c | 2 - libc/calls/getppid-nt.c | 39 + libc/calls/getppid.c | 21 - libc/calls/internal.h | 1 + libc/crt/crt.S | 2 +- libc/fmt/kerrnonames.S | 308 ------- libc/fmt/strerror_r.c | 271 +++++- libc/fmt/unbing.c | 1 + libc/integral/c.inc | 7 + libc/integral/normalize.inc | 2 +- libc/intrin/asan.c | 805 ++++++++++++++++++ libc/intrin/asan.internal.h | 26 + libc/intrin/intrin.mk | 7 +- libc/{log => intrin}/somanyasan.S | 42 +- libc/log/asan.c | 453 ---------- libc/log/asan.internal.h | 22 - libc/log/backtrace2.c | 27 +- libc/log/checkfail.c | 16 +- libc/log/checkfail_ndebug.c | 2 +- libc/log/die.c | 19 +- libc/log/getttysize.c | 2 +- libc/log/isrunningundermake.c | 4 +- libc/log/isterminalinarticulate.c | 2 +- libc/log/log.h | 4 +- libc/log/log.mk | 22 +- libc/log/oncrash.c | 7 +- libc/nexgen32e/kcp437.S | 2 +- libc/nexgen32e/memcpy.S | 5 +- libc/nexgen32e/memset.S | 5 +- libc/runtime/{executive.S => cosmo.S} | 17 +- libc/runtime/finddebugbinary.c | 2 + libc/runtime/internal.h | 2 +- libc/runtime/memtrack.h | 2 +- libc/runtime/mmap.c | 4 +- libc/runtime/runtime.mk | 18 +- libc/runtime/winmain.greg.c | 7 +- libc/{nexgen32e => str}/bsf.c | 0 libc/{nexgen32e => str}/bsfl.c | 0 libc/{nexgen32e => str}/bsfll.c | 0 libc/{nexgen32e => str}/bsr.c | 0 libc/{nexgen32e => str}/bsrl.c | 0 libc/{nexgen32e => str}/bsrll.c | 0 libc/{nexgen32e => str}/crc32.S | 0 libc/{nexgen32e => str}/crc32c-pure.c | 0 libc/{nexgen32e => str}/crc32c-sse42.c | 0 libc/{nexgen32e => str}/crc32c.S | 0 libc/{nexgen32e => str}/crc32z.c | 0 libc/{nexgen32e => str}/ctz.c | 0 libc/{nexgen32e => str}/djbsort.c | 0 libc/{nexgen32e => str}/insertionsort.greg.c | 0 libc/str/memccpy.c | 3 +- libc/str/stpcpy.c | 40 +- libc/str/str.h | 12 + libc/str/str.mk | 4 +- libc/str/strcpy.c | 40 +- libc/str/strlen-pure.c | 50 ++ libc/str/tprecode16to8.c | 34 +- libc/str/tprecode8to16.c | 34 +- libc/str/undeflate.c | 21 +- libc/stubs/asan.S | 4 - libc/sysv/consts.sh | 14 +- libc/sysv/systemfive.S | 87 +- libc/testlib/fixturerunner.c | 4 +- libc/testlib/testlib.h | 74 +- libc/testlib/testlib.mk | 1 - libc/testlib/testmem.c | 179 ---- libc/x/tunbing.c | 43 + libc/x/x.h | 2 + libc/x/xslurp.c | 2 +- net/http/http.mk | 1 - test/ape/lib/smapsort_test.c | 5 +- test/ape/lib/test.mk | 1 + test/dsp/core/test.mk | 4 - test/dsp/scale/magikarp_test.c | 33 +- test/dsp/tty/windex_test.c | 14 +- test/libc/alg/comparator_test.c | 33 +- test/libc/alg/djbsort_test.c | 12 +- test/libc/alg/qsort_test.c | 5 +- test/libc/dns/dnsheader_test.c | 17 +- test/libc/dns/dnsnamecmp_test.c | 57 +- test/libc/dns/dnsquestion_test.c | 17 +- test/libc/dns/pascalifydnsname_test.c | 49 +- test/libc/fmt/palandprintf_test.c | 16 +- test/libc/fmt/test.mk | 1 - test/libc/intrin/pmulhrsw_test.c | 10 + test/libc/intrin/test.mk | 4 - test/libc/nexgen32e/lz4decode_test.c | 25 +- test/libc/nexgen32e/memmove_test.c | 17 +- test/libc/nexgen32e/memset_test.c | 15 +- test/libc/nexgen32e/strcaseconv_test.c | 21 +- test/libc/rand/devrand_test.c | 9 +- test/libc/rand/test.mk | 1 + test/libc/runtime/getdosargv_test.c | 89 +- test/libc/runtime/getdosenviron_test.c | 49 +- test/libc/runtime/mmap_test.c | 4 +- test/libc/runtime/test.mk | 7 - test/libc/sock/inet_ntop_test.c | 5 +- test/libc/sock/test.mk | 1 + test/libc/str/memccpy_test.c | 31 +- test/libc/str/memcpy_test.c | 40 +- test/libc/str/memmem_test.c | 51 +- test/libc/str/pututf16_test.c | 15 +- test/libc/str/strcmp_test.c | 106 +-- test/libc/str/strlen_test.c | 29 +- test/libc/str/strstr_test.c | 14 +- test/libc/str/strtok_r_test.c | 17 +- test/libc/str/tprecode16to8_test.c | 4 +- test/libc/str/tprecode8to16_test.c | 8 +- .../gc_test.c => tinymath/exp_test.c} | 63 +- test/libc/tinymath/ilogb_test.c | 29 + test/libc/tinymath/logb_test.c | 1 - .../libc/tinymath/pow10_test.c | 55 +- test/libc/tinymath/powl_test.c | 10 +- test/libc/tinymath/round_test.c | 224 +++-- test/libc/tinymath/test.mk | 4 +- test/net/http/test.mk | 4 - test/tool/viz/lib/bilinearscale_test.c | 90 +- test/tool/viz/lib/halfblit_test.c | 27 +- third_party/chibicc/as.c | 16 +- third_party/chibicc/test/test.mk | 7 +- third_party/dlmalloc/dlmalloc-usable.c | 10 - third_party/dlmalloc/dlmalloc.c | 100 ++- third_party/dlmalloc/dlmemalign-impl.c | 70 -- third_party/dlmalloc/dlmemalign.c | 7 - third_party/stb/stb.mk | 6 - third_party/third_party.mk | 7 +- third_party/zlib/zlib.mk | 1 + tool/build/blinkenlights.c | 55 +- tool/build/calculator.c | 2 +- tool/build/emubin/emubin.mk | 4 + tool/build/lib/buildlib.mk | 6 - tool/build/lib/machine.c | 1 + tool/emacs/cosmo-c-keywords.el | 1 + tool/emacs/cosmo-cpp-constants.el | 1 + tool/emacs/cosmo-stuff.el | 4 +- tool/net/net.mk | 7 - tool/viz/lib/vizlib.mk | 6 - tool/viz/printvideo.c | 2 +- tool/viz/viz.mk | 6 - tool/viz/xterm256gradient.c | 77 ++ 153 files changed, 2545 insertions(+), 2077 deletions(-) create mode 100644 libc/calls/getppid-nt.c delete mode 100644 libc/fmt/kerrnonames.S create mode 100644 libc/intrin/asan.c create mode 100644 libc/intrin/asan.internal.h rename libc/{log => intrin}/somanyasan.S (91%) delete mode 100644 libc/log/asan.c delete mode 100644 libc/log/asan.internal.h rename libc/runtime/{executive.S => cosmo.S} (92%) rename libc/{nexgen32e => str}/bsf.c (100%) rename libc/{nexgen32e => str}/bsfl.c (100%) rename libc/{nexgen32e => str}/bsfll.c (100%) rename libc/{nexgen32e => str}/bsr.c (100%) rename libc/{nexgen32e => str}/bsrl.c (100%) rename libc/{nexgen32e => str}/bsrll.c (100%) rename libc/{nexgen32e => str}/crc32.S (100%) rename libc/{nexgen32e => str}/crc32c-pure.c (100%) rename libc/{nexgen32e => str}/crc32c-sse42.c (100%) rename libc/{nexgen32e => str}/crc32c.S (100%) rename libc/{nexgen32e => str}/crc32z.c (100%) rename libc/{nexgen32e => str}/ctz.c (100%) rename libc/{nexgen32e => str}/djbsort.c (100%) rename libc/{nexgen32e => str}/insertionsort.greg.c (100%) create mode 100644 libc/str/strlen-pure.c delete mode 100644 libc/testlib/testmem.c create mode 100644 libc/x/tunbing.c rename test/libc/{runtime/gc_test.c => tinymath/exp_test.c} (56%) create mode 100644 test/libc/tinymath/ilogb_test.c rename libc/runtime/spawn.S => test/libc/tinymath/pow10_test.c (64%) delete mode 100644 third_party/dlmalloc/dlmalloc-usable.c delete mode 100644 third_party/dlmalloc/dlmemalign-impl.c delete mode 100644 third_party/dlmalloc/dlmemalign.c create mode 100644 tool/viz/xterm256gradient.c diff --git a/ape/lib/apelib.mk b/ape/lib/apelib.mk index 2b38a38e..f7cf6866 100644 --- a/ape/lib/apelib.mk +++ b/ape/lib/apelib.mk @@ -19,8 +19,13 @@ APE_LIB_A_OBJS = \ $(APE_LIB_A_SRCS_S:%.S=o/$(MODE)/%.o) \ $(APE_LIB_A_SRCS_C:%.c=o/$(MODE)/%.o) +APE_LIB_A_DIRECTDEPS = \ + LIBC_NEXGEN32E \ + LIBC_INTRIN \ + LIBC_STR \ + LIBC_STUBS + APE_LIB_A_CHECKS = $(APE_LIB_A_HDRS:%=o/$(MODE)/%.ok) -APE_LIB_A_DIRECTDEPS = LIBC_STR LIBC_NEXGEN32E LIBC_STUBS APE_LIB_A_DEPS = $(call uniq,$(foreach x,$(APE_LIB_A_DIRECTDEPS),$($(x)))) $(APE_LIB_A): ape/lib/ $(APE_LIB_A).pkg $(APE_LIB_A_OBJS) diff --git a/build/compile b/build/compile index 197518fc..bfef2718 100755 --- a/build/compile +++ b/build/compile @@ -86,6 +86,9 @@ for x; do -mno-vzeroupper) set -- "$@" "$x" -Wa,-msse2avx -D__MNO_VZEROUPPER__ ;; + -fsanitize=address) + set -- "$@" "$x" -D__FSANITIZE_ADDRESS__ + ;; -fsanitize=undefined) set -- "$@" "$x" -D__FSANITIZE_UNDEFINED__ COUNTERMAND="$COUNTERMAND -fno-data-sections" # sqlite.o diff --git a/build/config.mk b/build/config.mk index 07c7446b..ea6e01e2 100644 --- a/build/config.mk +++ b/build/config.mk @@ -94,15 +94,13 @@ CONFIG_CPPFLAGS += \ CONFIG_CCFLAGS += \ $(BACKTRACES) \ $(FTRACE) \ + -O1 \ -fno-inline CONFIG_COPTS += \ $(SECURITY_BLANKETS) \ $(SANITIZER) -CONFIG_COPTS += \ - -ftrapv - TARGET_ARCH ?= \ -msse3 diff --git a/build/definitions.mk b/build/definitions.mk index 4359b9c2..c135e0bd 100644 --- a/build/definitions.mk +++ b/build/definitions.mk @@ -104,14 +104,15 @@ FTRACE = \ SANITIZER = \ -fsanitize=leak \ - -fsanitize=undefined \ + -fsanitize=address \ -fsanitize=implicit-signed-integer-truncation \ -fsanitize=implicit-integer-sign-change NO_MAGIC = \ -mno-fentry \ -fno-stack-protector \ - -fno-sanitize=all + -fno-sanitize=all \ + -fwrapv OLD_CODE = \ -fno-strict-aliasing \ diff --git a/build/mkdeps b/build/mkdeps index b6919ca4..e1d83bf1 100755 --- a/build/mkdeps +++ b/build/mkdeps @@ -2,16 +2,16 @@ #-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐ #───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘ -if [ -x "o/$MODE/tool/build/mkdeps.com" ]; then - set -- "o/$MODE/tool/build/mkdeps.com" "$@" -else +#if [ -x "o/$MODE/tool/build/mkdeps.com" ]; then +# set -- "o/$MODE/tool/build/mkdeps.com" "$@" +#else if [ ! -x o/build/bootstrap/mkdeps.com ]; then mkdir -p o/build/bootstrap && cp -a build/bootstrap/mkdeps.com \ o/build/bootstrap/mkdeps.com || exit fi set -- o/build/bootstrap/mkdeps.com "$@" -fi +#fi if [ "$SILENT" = "0" ]; then printf "%s\n" "$*" >&2 diff --git a/dsp/core/core.mk b/dsp/core/core.mk index 7f06a588..d4e130f3 100644 --- a/dsp/core/core.mk +++ b/dsp/core/core.mk @@ -26,6 +26,7 @@ DSP_CORE_A_CHECKS = \ DSP_CORE_A_DIRECTDEPS = \ LIBC_NEXGEN32E \ LIBC_MEM \ + LIBC_INTRIN \ LIBC_TINYMATH \ LIBC_STUBS @@ -57,12 +58,6 @@ o/$(MODE)/dsp/core/det3.o: \ OVERRIDE_CFLAGS += \ -ffast-math -# ifeq (,$(MODE)) -# $(DSP_CORE_OBJS): \ -# OVERRIDE_CFLAGS += \ -# -fsanitize=address -# endif - DSP_CORE_LIBS = $(foreach x,$(DSP_CORE_ARTIFACTS),$($(x))) DSP_CORE_SRCS = $(foreach x,$(DSP_CORE_ARTIFACTS),$($(x)_SRCS)) DSP_CORE_HDRS = $(foreach x,$(DSP_CORE_ARTIFACTS),$($(x)_HDRS)) diff --git a/dsp/tty/hidecursor.c b/dsp/tty/hidecursor.c index 638be2c6..b5dfa895 100644 --- a/dsp/tty/hidecursor.c +++ b/dsp/tty/hidecursor.c @@ -30,7 +30,7 @@ static int ttysetcursor(int fd, bool visible) { struct NtConsoleCursorInfo ntcursor; char code[8] = "\e[?25l"; - if (isterminalinarticulate()) return 0; + if (IsTerminalInarticulate()) return 0; if (visible) code[5] = 'h'; if (SupportsWindows()) { GetConsoleCursorInfo(GetStdHandle(kNtStdOutputHandle), &ntcursor); diff --git a/dsp/tty/tty.mk b/dsp/tty/tty.mk index 06b6f65a..33097971 100644 --- a/dsp/tty/tty.mk +++ b/dsp/tty/tty.mk @@ -59,12 +59,6 @@ o/$(MODE)/dsp/tty/ttyraster.o: \ OVERRIDE_CFLAGS += \ $(MATHEMATICAL) -# ifeq (,$(MODE)) -# $(DSP_TTY_OBJS): \ -# OVERRIDE_CFLAGS += \ -# -fsanitize=address -# endif - DSP_TTY_LIBS = $(foreach x,$(DSP_TTY_ARTIFACTS),$($(x))) DSP_TTY_SRCS = $(foreach x,$(DSP_TTY_ARTIFACTS),$($(x)_SRCS)) DSP_TTY_HDRS = $(foreach x,$(DSP_TTY_ARTIFACTS),$($(x)_HDRS)) diff --git a/dsp/tty/windex.S b/dsp/tty/windex.S index b659cbe5..c4c6ab15 100644 --- a/dsp/tty/windex.S +++ b/dsp/tty/windex.S @@ -32,7 +32,7 @@ windex: .quad 0 ezlea windex$sse4,dx testb X86_HAVE(AVX2)+kCpuids(%rip) cmovz %rdx,%rax -#endif /* AVX */ +#endif /* AVX2 */ #if !X86_NEED(SSE4_2) ezlea windex$k8,dx testb X86_HAVE(SSE4_2)+kCpuids(%rip) diff --git a/examples/crashreport.c b/examples/crashreport.c index 2c837214..9cf38a37 100644 --- a/examples/crashreport.c +++ b/examples/crashreport.c @@ -86,9 +86,9 @@ int main(int argc, char *argv[]) { "movd\t%rax,%xmm14\n\t" "mov\t$0xffffffffffffffff,%rax\n\t" "movd\t%rax,%xmm15\n\t" - "fldpi\n\t"); - - res = *(int *)(intptr_t)boo / boo; + "fldpi\n\t" + "xor\t%eax,%eax\n\t" + "div\t%eax\n\t"); return res; } diff --git a/examples/examples.mk b/examples/examples.mk index 58d4554e..3b96bb13 100644 --- a/examples/examples.mk +++ b/examples/examples.mk @@ -48,7 +48,6 @@ EXAMPLES_DIRECTDEPS = \ LIBC_FMT \ LIBC_INTRIN \ LIBC_LOG \ - LIBC_LOG_ASAN \ LIBC_MEM \ LIBC_NEXGEN32E \ LIBC_NT_KERNEL32 \ diff --git a/libc/calls/chdir.c b/libc/calls/chdir.c index 0ebbf1b9..4f95461e 100644 --- a/libc/calls/chdir.c +++ b/libc/calls/chdir.c @@ -16,10 +16,8 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/calls.h" #include "libc/calls/internal.h" #include "libc/dce.h" -#include "libc/sysv/errfuns.h" /** * Sets current directory. diff --git a/libc/calls/creat.c b/libc/calls/creat.c index 53ad1b0c..a16f076b 100644 --- a/libc/calls/creat.c +++ b/libc/calls/creat.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" +#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/o.h" /** @@ -35,5 +36,5 @@ * @asyncsignalsafe */ nodiscard int creat(const char *file, uint32_t mode) { - return open(file, O_CREAT | O_WRONLY | O_TRUNC, mode); + return openat(AT_FDCWD, file, O_CREAT | O_WRONLY | O_TRUNC, mode); } diff --git a/libc/calls/dup3.c b/libc/calls/dup3.c index cfd227f0..92041408 100644 --- a/libc/calls/dup3.c +++ b/libc/calls/dup3.c @@ -33,10 +33,8 @@ * unless it's equal to oldfd, in which case dup2() is a no-op * @flags can have O_CLOEXEC * @see dup(), dup2() - * @syscall */ int dup3(int oldfd, int newfd, int flags) { - if (oldfd == newfd) return einval(); if (!IsWindows()) { return dup3$sysv(oldfd, newfd, flags); } else { diff --git a/libc/calls/getppid-nt.c b/libc/calls/getppid-nt.c new file mode 100644 index 00000000..c95cd61e --- /dev/null +++ b/libc/calls/getppid-nt.c @@ -0,0 +1,39 @@ +/*-*- 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 2021 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/internal.h" +#include "libc/dce.h" +#include "libc/nt/nt/process.h" +#include "libc/nt/ntdll.h" +#include "libc/nt/process.h" +#include "libc/nt/runtime.h" +#include "libc/nt/struct/processbasicinformation.h" + +textwindows int getppid$nt(void) { + struct NtProcessBasicInformation ProcessInformation; + uint32_t gotsize = 0; + if (!NtError( + NtQueryInformationProcess(GetCurrentProcess(), 0, &ProcessInformation, + sizeof(ProcessInformation), &gotsize)) && + gotsize >= sizeof(ProcessInformation) && + ProcessInformation.InheritedFromUniqueProcessId) { + /* TODO(jart): Fix type mismatch and do we need to close this? */ + return ProcessInformation.InheritedFromUniqueProcessId; + } + return GetCurrentProcessId(); +} diff --git a/libc/calls/getppid.c b/libc/calls/getppid.c index 238be618..5801ec59 100644 --- a/libc/calls/getppid.c +++ b/libc/calls/getppid.c @@ -16,28 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/calls.h" #include "libc/calls/internal.h" -#include "libc/dce.h" -#include "libc/nt/nt/process.h" -#include "libc/nt/ntdll.h" -#include "libc/nt/process.h" -#include "libc/nt/runtime.h" -#include "libc/nt/struct/processbasicinformation.h" - -static textwindows noinline int32_t getppid$nt(void) { - struct NtProcessBasicInformation ProcessInformation; - uint32_t gotsize = 0; - if (!NtError( - NtQueryInformationProcess(GetCurrentProcess(), 0, &ProcessInformation, - sizeof(ProcessInformation), &gotsize)) && - gotsize >= sizeof(ProcessInformation) && - ProcessInformation.InheritedFromUniqueProcessId) { - /* TODO(jart): Fix type mismatch and do we need to close this? */ - return ProcessInformation.InheritedFromUniqueProcessId; - } - return GetCurrentProcessId(); -} /** * Returns parent process id. diff --git a/libc/calls/internal.h b/libc/calls/internal.h index 7c0c89dd..195d5acf 100644 --- a/libc/calls/internal.h +++ b/libc/calls/internal.h @@ -240,6 +240,7 @@ int fork$nt(void) hidden; int fstat$nt(i64, struct stat *) hidden; int fstatat$nt(int, const char *, struct stat *, uint32_t) hidden; int ftruncate$nt(int, u64) hidden; +int getppid$nt(void) hidden; int getpriority$nt(int) hidden; int getrusage$nt(int, struct rusage *) hidden; int gettimeofday$nt(struct timeval *, struct timezone *) hidden; diff --git a/libc/crt/crt.S b/libc/crt/crt.S index 1e970263..ad70ccc6 100644 --- a/libc/crt/crt.S +++ b/libc/crt/crt.S @@ -53,7 +53,7 @@ _start: test %rdi,%rdi repnz scasq mov %rdi,%rcx # auxv mov %ebx,%edi - call _executive + call cosmo 9: ud2 .endfn _start,weak,hidden diff --git a/libc/fmt/kerrnonames.S b/libc/fmt/kerrnonames.S deleted file mode 100644 index 845414c6..00000000 --- a/libc/fmt/kerrnonames.S +++ /dev/null @@ -1,308 +0,0 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 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/notice.inc" -#include "libc/macros.h" -.source __FILE__ - -/ Embeds ASCII names for errno constants into binary. - .section .rodata,"aS",@progbits -kErrnoNames: -/ - .asciz "2BIG" - .asciz "ACCES" - .asciz "ADDRINUSE" - .asciz "ADDRNOTAVAIL" - .asciz "ADV" - .asciz "AFNOSUPPORT" - .asciz "AGAIN" - .asciz "ALREADY" - .asciz "BADE" - .asciz "BADF" - .asciz "BADFD" - .asciz "BADMSG" - .asciz "BADR" - .asciz "BADRQC" - .asciz "BADSLT" - .asciz "BFONT" - .asciz "BUSY" - .asciz "CANCELED" - .asciz "CHILD" - .asciz "CHRNG" - .asciz "COMM" - .asciz "CONNABORTED" - .asciz "CONNREFUSED" - .asciz "CONNRESET" - .asciz "DEADLK" - .asciz "DESTADDRREQ" - .asciz "DOM" - .asciz "DOTDOT" - .asciz "DQUOT" - .asciz "EXIST" - .asciz "FAULT" - .asciz "FBIG" - .asciz "HOSTDOWN" - .asciz "HOSTUNREACH" - .asciz "HWPOISON" - .asciz "IDRM" - .asciz "ILSEQ" - .asciz "INPROGRESS" - .asciz "INTR" - .asciz "INVAL" - .asciz "IO" - .asciz "ISCONN" - .asciz "ISDIR" - .asciz "ISNAM" - .asciz "KEYEXPIRED" - .asciz "KEYREJECTED" - .asciz "KEYREVOKED" - .asciz "L2HLT" - .asciz "L2NSYNC" - .asciz "L3HLT" - .asciz "L3RST" - .asciz "LIBACC" - .asciz "LIBBAD" - .asciz "LIBEXEC" - .asciz "LIBMAX" - .asciz "LIBSCN" - .asciz "LNRNG" - .asciz "LOOP" - .asciz "MEDIUMTYPE" - .asciz "MFILE" - .asciz "MLINK" - .asciz "MSGSIZE" - .asciz "MULTIHOP" - .asciz "NAMETOOLONG" - .asciz "NAVAIL" - .asciz "NETDOWN" - .asciz "NETRESET" - .asciz "NETUNREACH" - .asciz "NFILE" - .asciz "NOANO" - .asciz "NOBUFS" - .asciz "NOCSI" - .asciz "NODATA" - .asciz "NODEV" - .asciz "NOENT" - .asciz "NOEXEC" - .asciz "NOKEY" - .asciz "NOLCK" - .asciz "NOLINK" - .asciz "NOMEDIUM" - .asciz "NOMEM" - .asciz "NOMSG" - .asciz "NONET" - .asciz "NOPKG" - .asciz "NOPROTOOPT" - .asciz "NOSPC" - .asciz "NOSR" - .asciz "NOSTR" - .asciz "NOSYS" - .asciz "NOTBLK" - .asciz "NOTCONN" - .asciz "NOTDIR" - .asciz "NOTEMPTY" - .asciz "NOTNAM" - .asciz "NOTRECOVERABLE" - .asciz "NOTSOCK" - .asciz "NOTSUP" - .asciz "NOTTY" - .asciz "NOTUNIQ" - .asciz "NXIO" - .asciz "OPNOTSUPP" - .asciz "OVERFLOW" - .asciz "OWNERDEAD" - .asciz "PERM" - .asciz "PFNOSUPPORT" - .asciz "PIPE" - .asciz "PROTO" - .asciz "PROTONOSUPPORT" - .asciz "PROTOTYPE" - .asciz "RANGE" - .asciz "REMCHG" - .asciz "REMOTE" - .asciz "REMOTEIO" - .asciz "RESTART" - .asciz "RFKILL" - .asciz "ROFS" - .asciz "SHUTDOWN" - .asciz "SOCKTNOSUPPORT" - .asciz "SPIPE" - .asciz "SRCH" - .asciz "SRMNT" - .asciz "STALE" - .asciz "STRPIPE" - .asciz "TIME" - .asciz "TIMEDOUT" - .asciz "TOOMANYREFS" - .asciz "TXTBSY" - .asciz "UCLEAN" - .asciz "UNATCH" - .asciz "USERS" - .asciz "XDEV" - .asciz "XFULL" -/ - .byte 0 - .endobj kErrnoNames,globl,hidden - .previous - -/ Pulls errno constants into linkage. -/ -/ @assume linker relocates these in sorted order -/ @assume linker invoked as LC_ALL=C ld ... -/ @see libc/sysv/systemfive.S -/ @see libc/sysv/consts/syscon.h - .yoink E2BIG - .yoink EACCES - .yoink EADDRINUSE - .yoink EADDRNOTAVAIL - .yoink EADV - .yoink EAFNOSUPPORT - .yoink EAGAIN - .yoink EALREADY - .yoink EBADE - .yoink EBADF - .yoink EBADFD - .yoink EBADMSG - .yoink EBADR - .yoink EBADRQC - .yoink EBADSLT - .yoink EBFONT - .yoink EBUSY - .yoink ECANCELED - .yoink ECHILD - .yoink ECHRNG - .yoink ECOMM - .yoink ECONNABORTED - .yoink ECONNREFUSED - .yoink ECONNRESET - .yoink EDEADLK - .yoink EDESTADDRREQ - .yoink EDOM - .yoink EDOTDOT - .yoink EDQUOT - .yoink EEXIST - .yoink EFAULT - .yoink EFBIG - .yoink EHOSTDOWN - .yoink EHOSTUNREACH - .yoink EHWPOISON - .yoink EIDRM - .yoink EILSEQ - .yoink EINPROGRESS - .yoink EINTR - .yoink EINVAL - .yoink EIO - .yoink EISCONN - .yoink EISDIR - .yoink EISNAM - .yoink EKEYEXPIRED - .yoink EKEYREJECTED - .yoink EKEYREVOKED - .yoink EL2HLT - .yoink EL2NSYNC - .yoink EL3HLT - .yoink EL3RST - .yoink ELIBACC - .yoink ELIBBAD - .yoink ELIBEXEC - .yoink ELIBMAX - .yoink ELIBSCN - .yoink ELNRNG - .yoink ELOOP - .yoink EMEDIUMTYPE - .yoink EMFILE - .yoink EMLINK - .yoink EMSGSIZE - .yoink EMULTIHOP - .yoink ENAMETOOLONG - .yoink ENAVAIL - .yoink ENETDOWN - .yoink ENETRESET - .yoink ENETUNREACH - .yoink ENFILE - .yoink ENOANO - .yoink ENOBUFS - .yoink ENOCSI - .yoink ENODATA - .yoink ENODEV - .yoink ENOENT - .yoink ENOEXEC - .yoink ENOKEY - .yoink ENOLCK - .yoink ENOLINK - .yoink ENOMEDIUM - .yoink ENOMEM - .yoink ENOMSG - .yoink ENONET - .yoink ENOPKG - .yoink ENOPROTOOPT - .yoink ENOSPC - .yoink ENOSR - .yoink ENOSTR - .yoink ENOSYS - .yoink ENOTBLK - .yoink ENOTCONN - .yoink ENOTDIR - .yoink ENOTEMPTY - .yoink ENOTNAM - .yoink ENOTRECOVERABLE - .yoink ENOTSOCK - .yoink ENOTSUP - .yoink ENOTTY - .yoink ENOTUNIQ - .yoink ENXIO - .yoink EOPNOTSUPP - .yoink EOVERFLOW - .yoink EOWNERDEAD - .yoink EPERM - .yoink EPFNOSUPPORT - .yoink EPIPE - .yoink EPROTO - .yoink EPROTONOSUPPORT - .yoink EPROTOTYPE - .yoink ERANGE - .yoink EREMCHG - .yoink EREMOTE - .yoink EREMOTEIO - .yoink ERESTART - .yoink ERFKILL - .yoink EROFS - .yoink ESHUTDOWN - .yoink ESOCKTNOSUPPORT - .yoink ESPIPE - .yoink ESRCH - .yoink ESRMNT - .yoink ESTALE - .yoink ESTRPIPE - .yoink ETIME - .yoink ETIMEDOUT - .yoink ETOOMANYREFS - .yoink ETXTBSY - .yoink EUCLEAN - .yoink EUNATCH - .yoink EUSERS - .yoink EXDEV - .yoink EXFULL - - .type kErrnoStart,@object - .type kErrnoEnd,@object - .globl kErrnoStart, kErrnoEnd, EXFULL, E2BIG - .hidden kErrnoStart, kErrnoEnd - kErrnoStart = E2BIG - kErrnoEnd = EXFULL + 8 diff --git a/libc/fmt/strerror_r.c b/libc/fmt/strerror_r.c index 4fdd80c7..f28aafb4 100644 --- a/libc/fmt/strerror_r.c +++ b/libc/fmt/strerror_r.c @@ -26,8 +26,275 @@ #include "libc/nt/runtime.h" #include "libc/str/str.h" -const char *geterrname(int code) { - extern const char kErrnoNames[]; +STATIC_YOINK("E2BIG"); +STATIC_YOINK("EACCES"); +STATIC_YOINK("EADDRINUSE"); +STATIC_YOINK("EADDRNOTAVAIL"); +STATIC_YOINK("EADV"); +STATIC_YOINK("EAFNOSUPPORT"); +STATIC_YOINK("EAGAIN"); +STATIC_YOINK("EALREADY"); +STATIC_YOINK("EBADE"); +STATIC_YOINK("EBADF"); +STATIC_YOINK("EBADFD"); +STATIC_YOINK("EBADMSG"); +STATIC_YOINK("EBADR"); +STATIC_YOINK("EBADRQC"); +STATIC_YOINK("EBADSLT"); +STATIC_YOINK("EBFONT"); +STATIC_YOINK("EBUSY"); +STATIC_YOINK("ECANCELED"); +STATIC_YOINK("ECHILD"); +STATIC_YOINK("ECHRNG"); +STATIC_YOINK("ECOMM"); +STATIC_YOINK("ECONNABORTED"); +STATIC_YOINK("ECONNREFUSED"); +STATIC_YOINK("ECONNRESET"); +STATIC_YOINK("EDEADLK"); +STATIC_YOINK("EDESTADDRREQ"); +STATIC_YOINK("EDOM"); +STATIC_YOINK("EDOTDOT"); +STATIC_YOINK("EDQUOT"); +STATIC_YOINK("EEXIST"); +STATIC_YOINK("EFAULT"); +STATIC_YOINK("EFBIG"); +STATIC_YOINK("EHOSTDOWN"); +STATIC_YOINK("EHOSTUNREACH"); +STATIC_YOINK("EHWPOISON"); +STATIC_YOINK("EIDRM"); +STATIC_YOINK("EILSEQ"); +STATIC_YOINK("EINPROGRESS"); +STATIC_YOINK("EINTR"); +STATIC_YOINK("EINVAL"); +STATIC_YOINK("EIO"); +STATIC_YOINK("EISCONN"); +STATIC_YOINK("EISDIR"); +STATIC_YOINK("EISNAM"); +STATIC_YOINK("EKEYEXPIRED"); +STATIC_YOINK("EKEYREJECTED"); +STATIC_YOINK("EKEYREVOKED"); +STATIC_YOINK("EL2HLT"); +STATIC_YOINK("EL2NSYNC"); +STATIC_YOINK("EL3HLT"); +STATIC_YOINK("EL3RST"); +STATIC_YOINK("ELIBACC"); +STATIC_YOINK("ELIBBAD"); +STATIC_YOINK("ELIBEXEC"); +STATIC_YOINK("ELIBMAX"); +STATIC_YOINK("ELIBSCN"); +STATIC_YOINK("ELNRNG"); +STATIC_YOINK("ELOOP"); +STATIC_YOINK("EMEDIUMTYPE"); +STATIC_YOINK("EMFILE"); +STATIC_YOINK("EMLINK"); +STATIC_YOINK("EMSGSIZE"); +STATIC_YOINK("EMULTIHOP"); +STATIC_YOINK("ENAMETOOLONG"); +STATIC_YOINK("ENAVAIL"); +STATIC_YOINK("ENETDOWN"); +STATIC_YOINK("ENETRESET"); +STATIC_YOINK("ENETUNREACH"); +STATIC_YOINK("ENFILE"); +STATIC_YOINK("ENOANO"); +STATIC_YOINK("ENOBUFS"); +STATIC_YOINK("ENOCSI"); +STATIC_YOINK("ENODATA"); +STATIC_YOINK("ENODEV"); +STATIC_YOINK("ENOENT"); +STATIC_YOINK("ENOEXEC"); +STATIC_YOINK("ENOKEY"); +STATIC_YOINK("ENOLCK"); +STATIC_YOINK("ENOLINK"); +STATIC_YOINK("ENOMEDIUM"); +STATIC_YOINK("ENOMEM"); +STATIC_YOINK("ENOMSG"); +STATIC_YOINK("ENONET"); +STATIC_YOINK("ENOPKG"); +STATIC_YOINK("ENOPROTOOPT"); +STATIC_YOINK("ENOSPC"); +STATIC_YOINK("ENOSR"); +STATIC_YOINK("ENOSTR"); +STATIC_YOINK("ENOSYS"); +STATIC_YOINK("ENOTBLK"); +STATIC_YOINK("ENOTCONN"); +STATIC_YOINK("ENOTDIR"); +STATIC_YOINK("ENOTEMPTY"); +STATIC_YOINK("ENOTNAM"); +STATIC_YOINK("ENOTRECOVERABLE"); +STATIC_YOINK("ENOTSOCK"); +STATIC_YOINK("ENOTSUP"); +STATIC_YOINK("ENOTTY"); +STATIC_YOINK("ENOTUNIQ"); +STATIC_YOINK("ENXIO"); +STATIC_YOINK("EOPNOTSUPP"); +STATIC_YOINK("EOVERFLOW"); +STATIC_YOINK("EOWNERDEAD"); +STATIC_YOINK("EPERM"); +STATIC_YOINK("EPFNOSUPPORT"); +STATIC_YOINK("EPIPE"); +STATIC_YOINK("EPROTO"); +STATIC_YOINK("EPROTONOSUPPORT"); +STATIC_YOINK("EPROTOTYPE"); +STATIC_YOINK("ERANGE"); +STATIC_YOINK("EREMCHG"); +STATIC_YOINK("EREMOTE"); +STATIC_YOINK("EREMOTEIO"); +STATIC_YOINK("ERESTART"); +STATIC_YOINK("ERFKILL"); +STATIC_YOINK("EROFS"); +STATIC_YOINK("ESHUTDOWN"); +STATIC_YOINK("ESOCKTNOSUPPORT"); +STATIC_YOINK("ESPIPE"); +STATIC_YOINK("ESRCH"); +STATIC_YOINK("ESRMNT"); +STATIC_YOINK("ESTALE"); +STATIC_YOINK("ESTRPIPE"); +STATIC_YOINK("ETIME"); +STATIC_YOINK("ETIMEDOUT"); +STATIC_YOINK("ETOOMANYREFS"); +STATIC_YOINK("ETXTBSY"); +STATIC_YOINK("EUCLEAN"); +STATIC_YOINK("EUNATCH"); +STATIC_YOINK("EUSERS"); +STATIC_YOINK("EXDEV"); +STATIC_YOINK("EXFULL"); + +_Alignas(char) static const char kErrnoNames[] = "\ +2BIG\000\ +ACCES\000\ +ADDRINUSE\000\ +ADDRNOTAVAIL\000\ +ADV\000\ +AFNOSUPPORT\000\ +AGAIN\000\ +ALREADY\000\ +BADE\000\ +BADF\000\ +BADFD\000\ +BADMSG\000\ +BADR\000\ +BADRQC\000\ +BADSLT\000\ +BFONT\000\ +BUSY\000\ +CANCELED\000\ +CHILD\000\ +CHRNG\000\ +COMM\000\ +CONNABORTED\000\ +CONNREFUSED\000\ +CONNRESET\000\ +DEADLK\000\ +DESTADDRREQ\000\ +DOM\000\ +DOTDOT\000\ +DQUOT\000\ +EXIST\000\ +FAULT\000\ +FBIG\000\ +HOSTDOWN\000\ +HOSTUNREACH\000\ +HWPOISON\000\ +IDRM\000\ +ILSEQ\000\ +INPROGRESS\000\ +INTR\000\ +INVAL\000\ +IO\000\ +ISCONN\000\ +ISDIR\000\ +ISNAM\000\ +KEYEXPIRED\000\ +KEYREJECTED\000\ +KEYREVOKED\000\ +L2HLT\000\ +L2NSYNC\000\ +L3HLT\000\ +L3RST\000\ +LIBACC\000\ +LIBBAD\000\ +LIBEXEC\000\ +LIBMAX\000\ +LIBSCN\000\ +LNRNG\000\ +LOOP\000\ +MEDIUMTYPE\000\ +MFILE\000\ +MLINK\000\ +MSGSIZE\000\ +MULTIHOP\000\ +NAMETOOLONG\000\ +NAVAIL\000\ +NETDOWN\000\ +NETRESET\000\ +NETUNREACH\000\ +NFILE\000\ +NOANO\000\ +NOBUFS\000\ +NOCSI\000\ +NODATA\000\ +NODEV\000\ +NOENT\000\ +NOEXEC\000\ +NOKEY\000\ +NOLCK\000\ +NOLINK\000\ +NOMEDIUM\000\ +NOMEM\000\ +NOMSG\000\ +NONET\000\ +NOPKG\000\ +NOPROTOOPT\000\ +NOSPC\000\ +NOSR\000\ +NOSTR\000\ +NOSYS\000\ +NOTBLK\000\ +NOTCONN\000\ +NOTDIR\000\ +NOTEMPTY\000\ +NOTNAM\000\ +NOTRECOVERABLE\000\ +NOTSOCK\000\ +NOTSUP\000\ +NOTTY\000\ +NOTUNIQ\000\ +NXIO\000\ +OPNOTSUPP\000\ +OVERFLOW\000\ +OWNERDEAD\000\ +PERM\000\ +PFNOSUPPORT\000\ +PIPE\000\ +PROTO\000\ +PROTONOSUPPORT\000\ +PROTOTYPE\000\ +RANGE\000\ +REMCHG\000\ +REMOTE\000\ +REMOTEIO\000\ +RESTART\000\ +RFKILL\000\ +ROFS\000\ +SHUTDOWN\000\ +SOCKTNOSUPPORT\000\ +SPIPE\000\ +SRCH\000\ +SRMNT\000\ +STALE\000\ +STRPIPE\000\ +TIME\000\ +TIMEDOUT\000\ +TOOMANYREFS\000\ +TXTBSY\000\ +UCLEAN\000\ +UNATCH\000\ +USERS\000\ +XDEV\000\ +XFULL\000\ +\000"; + +const char *geterrname(long code) { const long *e; size_t i, n; e = &E2BIG; diff --git a/libc/fmt/unbing.c b/libc/fmt/unbing.c index 8473392e..e58fa248 100644 --- a/libc/fmt/unbing.c +++ b/libc/fmt/unbing.c @@ -43,6 +43,7 @@ static const int kCp437iMultimappings[] = { u'∈' << 8 | 0xEE, // ELEMENT-OF SIGN u'β' << 8 | 0xE1, // GREEK SMALL BETA u'ſ' << 8 | 0xF4, // LATIN SMALL LETTER LONG S + u'·' << 8 | 0xFA // MIDDLE DOT }; static int g_cp437i[256 + ARRAYLEN(kCp437iMultimappings)]; diff --git a/libc/integral/c.inc b/libc/integral/c.inc index c9d2b1f1..56aa255f 100644 --- a/libc/integral/c.inc +++ b/libc/integral/c.inc @@ -597,6 +597,13 @@ typedef uint64_t uintmax_t; #define nocallersavedregisters "need modern compiler" #endif +#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 408 || \ + __has_attribute(__no_sanitize_address__) +#define noasan __attribute__((__no_sanitize_address__)) +#else +#define noasan +#endif + #ifndef unreachable #define unreachable __builtin_unreachable() #endif diff --git a/libc/integral/normalize.inc b/libc/integral/normalize.inc index 553d23ba..d704d4e1 100644 --- a/libc/integral/normalize.inc +++ b/libc/integral/normalize.inc @@ -57,7 +57,7 @@ #endif #define BIGPAGESIZE 0x200000 -#define STACKSIZE 0x10000 +#define STACKSIZE 0x100000 #define FRAMESIZE 0x10000 /* 8086 */ #define PAGESIZE 0x1000 /* i386+ */ #define BUFSIZ 0x1000 /* best stdio default */ diff --git a/libc/intrin/asan.c b/libc/intrin/asan.c new file mode 100644 index 00000000..950d39c0 --- /dev/null +++ b/libc/intrin/asan.c @@ -0,0 +1,805 @@ +/*-*- 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 2020 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/alg/reverse.h" +#include "libc/bits/bits.h" +#include "libc/bits/weaken.h" +#include "libc/calls/calls.h" +#include "libc/intrin/asan.internal.h" +#include "libc/linux/exit.h" +#include "libc/linux/write.h" +#include "libc/log/log.h" +#include "libc/macros.h" +#include "libc/mem/hook/hook.h" +#include "libc/runtime/directmap.h" +#include "libc/runtime/memtrack.h" +#include "libc/runtime/runtime.h" +#include "libc/sysv/consts/auxv.h" +#include "libc/sysv/consts/map.h" +#include "libc/sysv/consts/prot.h" +#include "third_party/dlmalloc/dlmalloc.internal.h" + +STATIC_YOINK("_init_asan"); + +/** + * @fileoverview Cosmopolitan Address Sanitizer Runtime. + * + * Someone brilliant at Google figured out a way to improve upon memory + * protection. Rather than invent another Java or Rust they changed GCC + * so it can emit fast code, that checks the validity of each memory op + * with byte granularity, by probing shadow memory. + * + * - AddressSanitizer dedicates one-eighth of the virtual address space + * to its shadow memory and uses a direct mapping with a scale and + * offset to translate an application address to its corresponding + * shadow address. Given the application memory address Addr, the + * address of the shadow byte is computed as (Addr>>3)+Offset." + * + * - We use the following encoding for each shadow byte: 0 means that + * all 8 bytes of the corresponding application memory region are + * addressable; k (1 ≤ k ≤ 7) means that the first k bytes are + * addressible; any negative value indicates that the entire 8-byte + * word is unaddressable. We use different negative values to + * distinguish between different kinds of unaddressable memory (heap + * redzones, stack redzones, global redzones, freed memory). + * + * Here's what the generated code looks like for 64-bit reads: + * + * movq %addr,%tmp + * shrq $3,%tmp + * cmpb $0,0x7fff8000(%tmp) + * jnz abort + * movq (%addr),%dst + */ + +#define HOOK(HOOK, IMPL) \ + do { \ + if (weaken(HOOK)) { \ + *weaken(HOOK) = IMPL; \ + } \ + } while (0) + +#define REQUIRE(FUNC) \ + do { \ + if (!weaken(FUNC)) { \ + __asan_write_string("asan needs " #FUNC "\n"); \ + __asan_exit(100); \ + } \ + } while (0) + +struct AsanSourceLocation { + const char *filename; + int line; + int column; +}; + +struct AsanAccessInfo { + const uintptr_t addr; + const uintptr_t first_bad_addr; + size_t size; + bool iswrite; + unsigned long ip; +}; + +struct AsanGlobal { + const uintptr_t addr; + size_t size; + size_t size_with_redzone; + const void *name; + const void *module_name; + unsigned long has_cxx_init; + struct AsanSourceLocation *location; + char *odr_indicator; +}; + +struct AsanMorgue { + unsigned i; + void *p[16]; +}; + +static struct AsanMorgue __asan_morgue; + +static uint64_t __asan_bsrl(uint64_t x) { + return __builtin_clzll(x) ^ 63; +} + +static uint64_t __asan_roundup2pow(uint64_t x) { + return x > 1 ? 1ull << (__asan_bsrl(x - 1) + 1) : x ? 1 : 0; +} + +static uint64_t __asan_rounddown2pow(uint64_t x) { + return x ? 1ull << __asan_bsrl(x) : 0; +} + +static size_t __asan_strlen(const char *s) { + size_t n = 0; + while (*s++) ++n; + return n; +} + +static int __asan_strcmp(const char *l, const char *r) { + size_t i = 0; + while (l[i] == r[i] && r[i]) ++i; + return (l[i] & 0xff) - (r[i] & 0xff); +} + +static char *__asan_stpcpy(char *d, const char *s) { + size_t i; + for (i = 0;; ++i) { + if (!(d[i] = s[i])) { + return d + i; + } + } +} + +static void *__asan_repstosb(void *di, int al, size_t cx) { + asm("rep stosb" + : "=D"(di), "=c"(cx), "=m"(*(char(*)[cx])di) + : "0"(di), "1"(cx), "a"(al)); + return di; +} + +static void *__asan_memset(void *p, int c, size_t n) { + char *b; + size_t i; + uint64_t x; + b = p; + x = 0x0101010101010101 * (c & 0xff); + switch (n) { + case 0: + return p; + case 1: + __builtin_memcpy(b, &x, 1); + return p; + case 2: + __builtin_memcpy(b, &x, 2); + return p; + case 3: + __builtin_memcpy(b, &x, 2); + __builtin_memcpy(b + 1, &x, 2); + return p; + case 4: + __builtin_memcpy(b, &x, 4); + return p; + case 5: + case 6: + case 7: + __builtin_memcpy(b, &x, 4); + __builtin_memcpy(b + n - 4, &x, 4); + return p; + case 8: + __builtin_memcpy(b, &x, 8); + return p; + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + __builtin_memcpy(b, &x, 8); + __builtin_memcpy(b + n - 8, &x, 8); + return p; + default: + if (n <= 64) { + i = 0; + do { + __builtin_memcpy(b + i, &x, 8); + asm volatile("" ::: "memory"); + __builtin_memcpy(b + i + 8, &x, 8); + } while ((i += 16) + 16 <= n); + for (; i < n; ++i) b[i] = x; + } else { + __asan_repstosb(p, c, n); + } + return p; + } +} + +static void *__asan_mempcpy(void *dst, const void *src, size_t n) { + size_t i; + char *d, *s; + uint64_t a, b; + d = dst; + s = src; + switch (n) { + case 0: + return d; + case 1: + *d = *s; + return d + 1; + case 2: + __builtin_memcpy(&a, s, 2); + __builtin_memcpy(d, &a, 2); + return d + 2; + case 3: + __builtin_memcpy(&a, s, 2); + __builtin_memcpy(&b, s + 1, 2); + __builtin_memcpy(d, &a, 2); + __builtin_memcpy(d + 1, &b, 2); + return d + 3; + case 4: + __builtin_memcpy(&a, s, 4); + __builtin_memcpy(d, &a, 4); + return d + 4; + case 5: + case 6: + case 7: + __builtin_memcpy(&a, s, 4); + __builtin_memcpy(&b, s + n - 4, 4); + __builtin_memcpy(d, &a, 4); + __builtin_memcpy(d + n - 4, &b, 4); + return d + n; + case 8: + __builtin_memcpy(&a, s, 8); + __builtin_memcpy(d, &a, 8); + return d + 8; + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + __builtin_memcpy(&a, s, 8); + __builtin_memcpy(&b, s + n - 8, 8); + __builtin_memcpy(d, &a, 8); + __builtin_memcpy(d + n - 8, &b, 8); + return d + n; + default: + i = 0; + do { + __builtin_memcpy(&a, s + i, 8); + asm volatile("" ::: "memory"); + __builtin_memcpy(d + i, &a, 8); + } while ((i += 8) + 8 <= n); + for (; i < n; ++i) d[i] = s[i]; + return d + i; + } +} + +static void *__asan_memcpy(void *dst, const void *src, size_t n) { + __asan_mempcpy(dst, src, n); + return dst; +} + +static void *__asan_memrchr(void *p, int c, size_t n) { + uint8_t *b; + for (c &= 0xff, b = p; n--;) { + if (b[n] == c) { + return b + n; + } + } + return NULL; +} + +static size_t __asan_int2hex(uint64_t x, char b[17], uint8_t k) { + int i; + char *p; + for (p = b; k > 0;) { + *p++ = "0123456789abcdef"[(x >> (k -= 4)) & 15]; + } + *p = '\0'; + return p - b; +} + +static size_t __asan_uint2str(uint64_t i, char *a) { + size_t j; + j = 0; + do { + a[j++] = i % 10 + '0'; + i /= 10; + } while (i > 0); + a[j] = '\0'; + reverse(a, j); + return j; +} + +static size_t __asan_int2str(int64_t i, char *a) { + if (i >= 0) return __asan_uint2str(i, a); + *a++ = '-'; + return 1 + __asan_uint2str(-i, a); +} + +void __asan_poison(uintptr_t p, size_t n, int kind) { + int k; + char *s; + if (!n) return; + if (p & 7) { + k = MIN(8 - (p & 7), n); + s = SHADOW(p); + if (*s == 0 || *s > (p & 7)) { + *s = p & 7; + } + n -= k; + p += k; + } + __asan_memset(SHADOW(p), kind, n >> 3); + if ((k = n & 7)) { + s = SHADOW(p + n); + if (*s < 0 || (*s > 0 && *s >= k)) { + *s = kind; + } + } +} + +void __asan_unpoison(uintptr_t p, size_t n) { + int k; + char *s; + if (!n) return; + if (p & 7) { + k = MIN(8 - (p & 7), n); + s = SHADOW(p); + *s = 0; + n -= k; + p += k; + } + __asan_memset(SHADOW(p), 0, n >> 3); + if ((k = n & 7)) { + s = SHADOW(p + n); + if (*s && *s < k) { + *s = k; + } + } +} + +static const char *__asan_dscribe_heap_poison(long c) { + switch (c) { + case kAsanHeapFree: + return "heap double free"; + case kAsanStackFree: + return "stack double free"; + case kAsanRelocated: + return "free after relocate"; + default: + return "this corruption"; + } +} + +static const char *__asan_describe_access_poison(int c) { + switch (c) { + case kAsanHeapFree: + return "heap use after free"; + case kAsanStackFree: + return "stack use after release"; + case kAsanRelocated: + return "heap use after relocate"; + case kAsanHeapUnderrun: + return "heap underrun"; + case kAsanHeapOverrun: + return "heap overrun"; + case kAsanGlobalOverrun: + return "global overrun"; + case kAsanGlobalUnregistered: + return "global unregistered"; + case kAsanStackUnderrun: + return "stack underflow"; + case kAsanStackOverrun: + return "stack overflow"; + case kAsanAllocaUnderrun: + return "alloca underflow"; + case kAsanAllocaOverrun: + return "alloca overflow"; + case kAsanUnscoped: + return "unscoped"; + case kAsanUnmapped: + return "unmapped"; + default: + return "poisoned"; + } +} + +static ssize_t __asan_write(const void *data, size_t size) { + ssize_t rc; + if (weaken(write)) { + if ((rc = weaken(write)(2, data, size)) != -1) { + return rc; + } + } + return LinuxWrite(2, data, size); +} + +static ssize_t __asan_write_string(const char *s) { + return __asan_write(s, __asan_strlen(s)); +} + +static wontreturn void __asan_exit(int rc) { + if (weaken(_Exit)) { + weaken(_Exit)(rc); + } else { + LinuxExit(rc); + } + for (;;) asm("hlt"); +} + +static wontreturn void __asan_abort(void) { + if (weaken(abort)) weaken(abort)(); + __asan_exit(134); +} + +static wontreturn void __asan_die(const char *msg) { + __asan_write_string(msg); + if (weaken(__die)) weaken(__die)(); + __asan_abort(); +} + +static char *__asan_report_start(char *p) { + bool ansi; + const char *term; + term = weaken(getenv) ? weaken(getenv)("TERM") : NULL; + ansi = !term || __asan_strcmp(term, "dumb") != 0; + if (ansi) p = __asan_stpcpy(p, "\r\e[J\e[1;91m"); + p = __asan_stpcpy(p, "asan error"); + if (ansi) p = __asan_stpcpy(p, "\e[0m"); + return __asan_stpcpy(p, ": "); +} + +static wontreturn void __asan_report_heap_fault(void *addr, long c) { + char *p, ibuf[21], buf[256]; + p = __asan_report_start(buf); + p = __asan_stpcpy(p, __asan_dscribe_heap_poison(c)); + p = __asan_stpcpy(p, " "); + p = __asan_mempcpy(p, ibuf, __asan_int2str(c, ibuf)); + p = __asan_stpcpy(p, " at 0x"); + p = __asan_mempcpy(p, ibuf, __asan_int2hex((intptr_t)addr, ibuf, 48)); + p = __asan_stpcpy(p, " shadow 0x"); + p = __asan_mempcpy(p, ibuf, __asan_int2hex((intptr_t)SHADOW(addr), ibuf, 48)); + p = __asan_stpcpy(p, "\r\n"); + __asan_die(buf); +} + +static wontreturn void __asan_report_memory_fault(uint8_t *addr, int size, + const char *kind) { + char *p, ibuf[21], buf[256]; + p = __asan_report_start(buf); + p = __asan_stpcpy(p, __asan_describe_access_poison(*SHADOW(addr))); + p = __asan_stpcpy(p, " "); + p = __asan_mempcpy(p, ibuf, __asan_int2str(size, ibuf)); + p = __asan_stpcpy(p, "-byte "); + p = __asan_stpcpy(p, kind); + p = __asan_stpcpy(p, " at 0x"); + p = __asan_mempcpy(p, ibuf, __asan_int2hex((intptr_t)addr, ibuf, 48)); + p = __asan_stpcpy(p, " shadow 0x"); + p = __asan_mempcpy(p, ibuf, __asan_int2hex((intptr_t)SHADOW(addr), ibuf, 48)); + p = __asan_stpcpy(p, "\r\n"); + __asan_die(buf); +} + +const void *__asan_morgue_add(void *p) { + void *r; + unsigned i, j; + for (;;) { + i = __asan_morgue.i; + j = (i + 1) & (ARRAYLEN(__asan_morgue.p) - 1); + if (cmpxchg(&__asan_morgue.i, i, j)) { + r = __asan_morgue.p[i]; + __asan_morgue.p[i] = p; + return r; + } + } +} + +static void __asan_morgue_flush(void) { + void *p; + unsigned i; + for (i = 0; i < ARRAYLEN(__asan_morgue.p); ++i) { + p = __asan_morgue.p[i]; + if (cmpxchg(__asan_morgue.p + i, p, NULL)) { + if (weaken(dlfree)) { + weaken(dlfree)(p); + } + } + } +} + +static size_t __asan_heap_size(size_t n) { + if (n < -8) { + return __asan_roundup2pow(ROUNDUP(n, 8) + 8); + } else { + return -1; + } +} + +static void *__asan_allocate(size_t a, size_t n, int underrun, int overrun) { + char *p; + size_t c; + if ((p = weaken(dlmemalign)(a, __asan_heap_size(n)))) { + c = weaken(dlmalloc_usable_size)(p); + __asan_unpoison((uintptr_t)p, n); + __asan_poison((uintptr_t)p - 16, 16, underrun); /* see dlmalloc design */ + __asan_poison((uintptr_t)p + n, c - n, overrun); + WRITE64BE(p + c - sizeof(n), n); + } + return p; +} + +static size_t __asan_malloc_usable_size(const void *p) { + size_t c, n; + if ((c = weaken(dlmalloc_usable_size)(p)) >= 8) { + if ((n = READ64BE((char *)p + c - sizeof(n))) <= c) { + return n; + } else { + __asan_report_heap_fault(p, n); + } + } else { + __asan_report_heap_fault(p, 0); + } +} + +static void __asan_deallocate(char *p, long kind) { + size_t c, n; + if ((c = weaken(dlmalloc_usable_size)(p)) >= 8) { + if ((n = READ64BE((char *)p + c - sizeof(n))) <= c) { + WRITE64BE((char *)p + c - sizeof(n), kind); + __asan_poison((uintptr_t)p, n, kind); + if (weaken(dlfree)) { + weaken(dlfree)(__asan_morgue_add(p)); + } + } else { + __asan_report_heap_fault(p, n); + } + } else { + __asan_report_heap_fault(p, 0); + } +} + +static void __asan_free(void *p) { + if (!p) return; + __asan_deallocate(p, kAsanHeapFree); +} + +static void *__asan_memalign(size_t align, size_t size) { + return __asan_allocate(align, size, kAsanHeapUnderrun, kAsanHeapOverrun); +} + +static void *__asan_malloc(size_t size) { + return __asan_memalign(16, size); +} + +static void *__asan_calloc(size_t nelem, size_t elsize) { + char *p; + size_t n; + if (__builtin_mul_overflow(nelem, elsize, &n)) n = -1; + if ((p = __asan_malloc(n))) __asan_memset(p, 0, n); + return p; +} + +static void *__asan_realloc(void *p, size_t n) { + char *p2; + size_t c, m; + if (p) { + if (n) { + if ((c = weaken(dlmalloc_usable_size)(p)) < 8) + __asan_report_heap_fault(p, 0); + if ((m = READ64BE((char *)p + c - sizeof(n))) > c) + __asan_report_heap_fault(p, m); + if (n <= m) { /* shrink */ + __asan_poison((uintptr_t)p + n, m - n, kAsanHeapOverrun); + WRITE64BE((char *)p + c - sizeof(n), n); + p2 = p; + } else if (n <= c - 8) { /* small growth */ + __asan_unpoison((uintptr_t)p + m, n - m); + WRITE64BE((char *)p + c - sizeof(n), n); + p2 = p; + } else if ((p2 = __asan_malloc(n))) { /* exponential growth */ + __asan_memcpy(p2, p, m); + __asan_deallocate(p, kAsanRelocated); + } + } else { + __asan_free(p); + p2 = NULL; + } + } else { + p2 = __asan_malloc(n); + } + return p2; +} + +static void *__asan_valloc(size_t n) { + return __asan_memalign(PAGESIZE, n); +} + +static void *__asan_pvalloc(size_t n) { + return __asan_valloc(ROUNDUP(n, PAGESIZE)); +} + +static int __asan_malloc_trim(size_t pad) { + __asan_morgue_flush(); + if (weaken(dlmalloc_trim)) { + return weaken(dlmalloc_trim)(pad); + } else { + return 0; + } +} + +void *__asan_stack_malloc(size_t size, int classid) { + return __asan_allocate(32, size, kAsanStackUnderrun, kAsanStackOverrun); +} + +void __asan_stack_free(char *p, size_t size, int classid) { + __asan_deallocate(p, kAsanStackFree); +} + +void __asan_handle_no_return_impl(uintptr_t rsp) { + __asan_unpoison(rsp, ROUNDUP(rsp, STACKSIZE) - rsp); +} + +void __asan_register_globals(struct AsanGlobal g[], int n) { + int i; + for (i = 0; i < n; ++i) { + __asan_unpoison(g[i].addr, g[i].size); + __asan_poison(g[i].addr + g[i].size, g[i].size_with_redzone - g[i].size, + kAsanGlobalOverrun); + } +} + +void __asan_unregister_globals(struct AsanGlobal g[], int n) { + int i; + for (i = 0; i < n; ++i) { + __asan_poison(g[i].addr, g[i].size_with_redzone, kAsanGlobalUnregistered); + } +} + +void __asan_report_load_impl(uint8_t *addr, int size) { + __asan_report_memory_fault(addr, size, "load"); +} + +void __asan_report_store_impl(uint8_t *addr, int size) { + __asan_report_memory_fault(addr, size, "store"); +} + +void __asan_alloca_poison(uintptr_t addr, size_t size) { + /* TODO(jart): Make sense of this function. */ + /* __asan_poison(addr - 32, 32, kAsanAllocaUnderrun); */ + __asan_poison(ROUNDUP(addr + size, 32), 32, kAsanAllocaOverrun); + __asan_unpoison(addr, ROUNDUP(addr + size, 32) - (addr + size) + 32 + size); +} + +void __asan_allocas_unpoison(uintptr_t x, uintptr_t y) { + if (x && x > y) __asan_unpoison(x, y - x); +} + +void *__asan_addr_is_in_fake_stack(void *fakestack, void *addr, void **beg, + void **end) { + return NULL; +} + +void *__asan_get_current_fake_stack(void) { + return NULL; +} + +void __asan_install_malloc_hooks(void) { + HOOK(hook$free, __asan_free); + HOOK(hook$malloc, __asan_malloc); + HOOK(hook$calloc, __asan_calloc); + HOOK(hook$valloc, __asan_valloc); + HOOK(hook$pvalloc, __asan_pvalloc); + HOOK(hook$realloc, __asan_realloc); + HOOK(hook$memalign, __asan_memalign); + HOOK(hook$malloc_trim, __asan_malloc_trim); + HOOK(hook$malloc_usable_size, __asan_malloc_usable_size); +} + +static bool __asan_is_mapped(int x) { + int i; + struct MemoryIntervals *m; + m = weaken(_mmi); + i = weaken(FindMemoryInterval)(m, x); + return i < m->i && x >= m->p[i].x && x <= m->p[i].y; +} + +void __asan_map_shadow(uintptr_t p, size_t n) { + int i, x, a, b; + struct DirectMap sm; + struct MemoryIntervals *m; + if (0x7fff8000 <= p && p < 0x100080000000) { + __asan_die("asan error: mmap can't shadow a shadow\r\n"); + } + m = weaken(_mmi); + a = (uintptr_t)SHADOW(p) >> 16; + b = ROUNDUP((uintptr_t)SHADOW(ROUNDUP((uintptr_t)p + n, 8)), 1 << 16) >> 16; + for (; a < b; ++a) { + if (!__asan_is_mapped(a)) { + sm = weaken(__mmap)( + (void *)((uintptr_t)a << 16), 1 << 16, PROT_READ | PROT_WRITE, + MAP_PRIVATE | *weaken(MAP_ANONYMOUS) | MAP_FIXED, -1, 0); + if (sm.addr == MAP_FAILED || + weaken(TrackMemoryInterval)( + m, a, a, sm.maphandle, PROT_READ | PROT_WRITE, + MAP_PRIVATE | *weaken(MAP_ANONYMOUS) | MAP_FIXED) == -1) { + __asan_abort(); + } + __asan_repstosb((void *)((uintptr_t)a << 16), kAsanUnmapped, 1 << 16); + } + } + __asan_unpoison((uintptr_t)p, n); +} + +static textstartup void __asan_shadow_string(char *s) { + __asan_map_shadow((uintptr_t)s, __asan_strlen(s) + 1); +} + +static textstartup void __asan_shadow_auxv(intptr_t *auxv) { + size_t i; + for (i = 0; auxv[i]; i += 2) { + if (weaken(AT_RANDOM) && auxv[i] == *weaken(AT_RANDOM)) { + __asan_map_shadow(auxv[i + 1], 16); + } else if (weaken(AT_EXECFN) && auxv[i] == *weaken(AT_EXECFN)) { + __asan_shadow_string((char *)auxv[i + 1]); + } else if (weaken(AT_PLATFORM) && auxv[i] == *weaken(AT_PLATFORM)) { + __asan_shadow_string((char *)auxv[i + 1]); + } + } + __asan_map_shadow((uintptr_t)auxv, (i + 2) * sizeof(intptr_t)); +} + +static textstartup void __asan_shadow_string_list(char **list) { + size_t i; + for (i = 0; list[i]; ++i) { + __asan_shadow_string(list[i]); + } + __asan_map_shadow((uintptr_t)list, (i + 1) * sizeof(char *)); +} + +static textstartup void __asan_shadow_existing_mappings(void) { + size_t i; + struct MemoryIntervals m; + __asan_memcpy(&m, weaken(_mmi), sizeof(m)); + for (i = 0; i < m.i; ++i) { + __asan_map_shadow((uintptr_t)m.p[i].x << 16, + (uintptr_t)(m.p[i].y - m.p[i].x + 1) << 16); + } +} + +static textstartup bool IsMemoryManagementRuntimeLinked(void) { + return weaken(_mmi) && weaken(__mmap) && weaken(MAP_ANONYMOUS) && + weaken(FindMemoryInterval) && weaken(TrackMemoryInterval); +} + +textstartup void __asan_init(int argc, char **argv, char **envp, + intptr_t *auxv) { + static bool once; + if (!cmpxchg(&once, false, true)) return; + REQUIRE(_mmi); + REQUIRE(__mmap); + REQUIRE(MAP_ANONYMOUS); + REQUIRE(FindMemoryInterval); + REQUIRE(TrackMemoryInterval); + if (weaken(hook$malloc) || weaken(hook$calloc) || weaken(hook$realloc) || + weaken(hook$pvalloc) || weaken(hook$valloc) || weaken(hook$free) || + weaken(hook$malloc_usable_size)) { + REQUIRE(dlmemalign); + REQUIRE(dlmalloc_usable_size); + } + __asan_shadow_existing_mappings(); + __asan_map_shadow((uintptr_t)_base, _end - _base); + __asan_shadow_string_list(argv); + __asan_shadow_string_list(envp); + __asan_shadow_auxv(auxv); + __asan_install_malloc_hooks(); +} + +static textstartup void __asan_ctor(void) { + if (weaken(__cxa_atexit)) { + weaken(__cxa_atexit)(__asan_morgue_flush, NULL, NULL); + } +} + +const void *const g_asan_ctor[] initarray = {__asan_ctor}; diff --git a/libc/intrin/asan.internal.h b/libc/intrin/asan.internal.h new file mode 100644 index 00000000..6e6bd3f6 --- /dev/null +++ b/libc/intrin/asan.internal.h @@ -0,0 +1,26 @@ +#ifndef COSMOPOLITAN_LIBC_INTRIN_ASAN_H_ +#define COSMOPOLITAN_LIBC_INTRIN_ASAN_H_ + +#define kAsanScale 3 +#define kAsanMagic 0x7fff8000 +#define kAsanHeapFree -1 +#define kAsanStackFree -2 +#define kAsanRelocated -3 +#define kAsanHeapUnderrun -4 +#define kAsanHeapOverrun -5 +#define kAsanGlobalOverrun -6 +#define kAsanGlobalUnregistered -7 +#define kAsanStackUnderrun -8 +#define kAsanStackOverrun -9 +#define kAsanAllocaUnderrun -10 +#define kAsanAllocaOverrun -11 +#define kAsanUnscoped -12 +#define kAsanUnmapped -13 + +#define SHADOW(x) ((char *)(((uintptr_t)(x) >> kAsanScale) + kAsanMagic)) + +void __asan_map_shadow(uintptr_t, size_t); +void __asan_poison(uintptr_t, size_t, int); +void __asan_unpoison(uintptr_t, size_t); + +#endif /* COSMOPOLITAN_LIBC_INTRIN_ASAN_H_ */ diff --git a/libc/intrin/intrin.mk b/libc/intrin/intrin.mk index bf3d7646..cd9a9192 100644 --- a/libc/intrin/intrin.mk +++ b/libc/intrin/intrin.mk @@ -41,7 +41,12 @@ $(LIBC_INTRIN_A).pkg: \ $(LIBC_INTRIN_A_OBJS): \ OVERRIDE_CFLAGS += \ - -fwrapv -O3 + $(NO_MAGIC) \ + -O3 + +o/$(MODE)/libc/intrin/asan.o: \ + OVERRIDE_CFLAGS += \ + -mgeneral-regs-only LIBC_INTRIN_LIBS = $(foreach x,$(LIBC_INTRIN_ARTIFACTS),$($(x))) LIBC_INTRIN_HDRS = $(foreach x,$(LIBC_INTRIN_ARTIFACTS),$($(x)_HDRS)) diff --git a/libc/log/somanyasan.S b/libc/intrin/somanyasan.S similarity index 91% rename from libc/log/somanyasan.S rename to libc/intrin/somanyasan.S index c31c7cb7..17df1d7d 100644 --- a/libc/log/somanyasan.S +++ b/libc/intrin/somanyasan.S @@ -17,7 +17,6 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/macros.h" -.privileged .source __FILE__ / @fileoverview Address Sanitizer Thunks @@ -48,9 +47,12 @@ __asan_report_load16: .endfn __asan_report_load16,globl OnReportLoad: pop %rsi - ezlea __asan_report_load_n,ax - jmp __asan_report_noreentry +/ 𝑠𝑙𝑖𝑑𝑒 .endfn OnReportLoad +__asan_report_load_n: + lea __asan_report_load_impl(%rip),%r11 + jmp __asan_report_noreentry + .endfn __asan_report_load_n,globl __asan_report_store1: push $1 @@ -78,21 +80,24 @@ __asan_report_store32: .endfn __asan_report_store32,globl ReportStore: pop %rsi - ezlea __asan_report_store_n,ax / 𝑠𝑙𝑖𝑑𝑒 .endfn ReportStore +__asan_report_store_n: + lea __asan_report_store_impl(%rip),%r11 +/ 𝑠𝑙𝑖𝑑𝑒 + .endfn __asan_report_store_n,globl __asan_report_noreentry: push %rbp mov %rsp,%rbp - cmpb $0,noreentry(%rip) + xor %eax,%eax + mov $1,%r10b + cmpxchg %r10b,__asan_noreentry(%rip) jnz 2f - incb noreentry(%rip) - call *%rax - decb noreentry(%rip) - pop %rbp + call *%r11 + decb __asan_noreentry(%rip) +2: pop %rbp ret -2: call abort .endfn __asan_report_noreentry __asan_stack_free_0: @@ -194,14 +199,27 @@ OnStackMalloc: .endfn OnStackMalloc __asan_handle_no_return: + push %rbp + mov %rsp,%rbp + lea 8(%rsp),%rdi + call __asan_handle_no_return_impl + pop %rbp ret .endfn __asan_handle_no_return,globl __asan_before_dynamic_init: + push %rbp + mov %rsp,%rbp + ud2 + pop %rbp ret .endfn __asan_before_dynamic_init,globl __asan_after_dynamic_init: + push %rbp + mov %rsp,%rbp + ud2 + pop %rbp ret .endfn __asan_after_dynamic_init,globl @@ -229,7 +247,7 @@ __asan_option_detect_stack_use_after_return: .previous .bss -noreentry: +__asan_noreentry: .byte 0 - .endobj noreentry + .endobj __asan_noreentry .previous diff --git a/libc/log/asan.c b/libc/log/asan.c deleted file mode 100644 index 819e9a14..00000000 --- a/libc/log/asan.c +++ /dev/null @@ -1,453 +0,0 @@ -/*-*- 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 2020 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/bits/safemacros.h" -#include "libc/bits/weaken.h" -#include "libc/calls/calls.h" -#include "libc/fmt/itoa.h" -#include "libc/log/asan.internal.h" -#include "libc/log/backtrace.internal.h" -#include "libc/log/log.h" -#include "libc/mem/hook/hook.h" -#include "libc/runtime/directmap.h" -#include "libc/runtime/memtrack.h" -#include "libc/runtime/runtime.h" -#include "libc/str/str.h" -#include "libc/sysv/consts/fileno.h" -#include "libc/sysv/consts/map.h" -#include "libc/sysv/consts/prot.h" -#include "third_party/dlmalloc/dlmalloc.internal.h" - -STATIC_YOINK("_init_asan"); - -/** - * @fileoverview Cosmopolitan Address Sanitizer Runtime. - * - * Someone brilliant at Google figured out a way to improve upon memory - * protection. Rather than invent another Java or Rust they changed GCC - * so it can emit fast code, that checks the validity of each memory op - * with byte granularity, by probing shadow memory. - * - * - AddressSanitizer dedicates one-eighth of the virtual address space - * to its shadow memory and uses a direct mapping with a scale and - * offset to translate an application address to its corresponding - * shadow address. Given the application memory address Addr, the - * address of the shadow byte is computed as (Addr>>3)+Offset." - * - * - We use the following encoding for each shadow byte: 0 means that - * all 8 bytes of the corresponding application memory region are - * addressable; k (1 ≤ k ≤ 7) means that the first k bytes are - * addressible; any negative value indicates that the entire 8-byte - * word is unaddressable. We use different negative values to - * distinguish between different kinds of unaddressable memory (heap - * redzones, stack redzones, global redzones, freed memory). - * - * Here's what the generated code looks like for 64-bit reads: - * - * movq %addr,%tmp - * shrq $3,%tmp - * cmpb $0,0x7fff8000(%tmp) - * jnz abort - * movq (%addr),%dst - */ - -#define HOOK(HOOK, IMPL) \ - if (weaken(HOOK)) { \ - *weaken(HOOK) = IMPL; \ - } - -struct AsanSourceLocation { - const char *filename; - int line; - int column; -}; - -struct AsanAccessInfo { - const char *addr; - const char *first_bad_addr; - size_t size; - bool iswrite; - unsigned long ip; -}; - -struct AsanGlobal { - const char *addr; - size_t size; - size_t size_with_redzone; - const void *name; - const void *module_name; - unsigned long has_cxx_init; - struct AsanSourceLocation *location; - char *odr_indicator; -}; - -struct AsanMorgue { - unsigned i; - void *p[16]; -}; - -static struct AsanMorgue __asan_morgue; - -static const char *__asan_dscribe_free_poison(int c) { - switch (c) { - case kAsanHeapFree: - return "heap double free"; - case kAsanRelocated: - return "free after relocate"; - case kAsanStackFree: - return "stack double free"; - default: - return "invalid pointer"; - } -} - -static const char *__asan_describe_access_poison(int c) { - switch (c) { - case kAsanHeapFree: - return "heap use after free"; - case kAsanStackFree: - return "stack use after release"; - case kAsanRelocated: - return "heap use after relocate"; - case kAsanHeapUnderrun: - return "heap underrun"; - case kAsanHeapOverrun: - return "heap overrun"; - case kAsanGlobalOverrun: - return "global overrun"; - case kAsanGlobalUnregistered: - return "global unregistered"; - case kAsanStackUnderrun: - return "stack underflow"; - case kAsanStackOverrun: - return "stack overflow"; - case kAsanAllocaOverrun: - return "alloca overflow"; - case kAsanUnscoped: - return "unscoped"; - default: - return "poisoned"; - } -} - -static wontreturn void __asan_die(const char *msg, size_t size) { - write(STDERR_FILENO, msg, size); - __die(); -} - -static char *__asan_report_start(char *p) { - bool ansi; - const char *term; - term = getenv("TERM"); - ansi = !term || strcmp(term, "dumb") != 0; - if (ansi) p = stpcpy(p, "\r\e[J\e[1;91m"); - p = stpcpy(p, "asan error"); - if (ansi) p = stpcpy(p, "\e[0m"); - return stpcpy(p, ": "); -} - -static wontreturn void __asan_report_deallocate_fault(void *addr, int c) { - char *p, ibuf[21], buf[256]; - p = __asan_report_start(buf); - p = stpcpy(p, __asan_dscribe_free_poison(c)); - p = stpcpy(p, " "); - p = mempcpy(p, ibuf, int64toarray_radix10(c, ibuf)); - p = stpcpy(p, " at 0x"); - p = mempcpy(p, ibuf, uint64toarray_fixed16((intptr_t)addr, ibuf, 48)); - p = stpcpy(p, "\r\n"); - __asan_die(buf, p - buf); -} - -static wontreturn void __asan_report_memory_fault(uint8_t *addr, int size, - const char *kind) { - char *p, ibuf[21], buf[256]; - p = __asan_report_start(buf); - p = stpcpy(p, __asan_describe_access_poison(*(char *)SHADOW((intptr_t)addr))); - p = stpcpy(p, " "); - p = mempcpy(p, ibuf, uint64toarray_radix10(size, ibuf)); - p = stpcpy(p, "-byte "); - p = stpcpy(p, kind); - p = stpcpy(p, " at 0x"); - p = mempcpy(p, ibuf, uint64toarray_fixed16((intptr_t)addr, ibuf, 48)); - p = stpcpy(p, "\r\n"); - __asan_die(buf, p - buf); -} - -static const void *__asan_morgue_add(void *p) { - void *r; - r = __asan_morgue.p[__asan_morgue.i]; - __asan_morgue.p[__asan_morgue.i] = p; - __asan_morgue.i += 1; - __asan_morgue.i &= ARRAYLEN(__asan_morgue.p) - 1; - return r; -} - -static void __asan_morgue_flush(void) { - void *p; - unsigned i; - for (i = 0; i < ARRAYLEN(__asan_morgue.p); ++i) { - p = __asan_morgue.p[i]; - __asan_morgue.p[i] = NULL; - dlfree(p); - } -} - -static void *__asan_allocate(size_t align, size_t size, int underrun, - int overrun) { - char *p, *s; - size_t q, r, i; - if (!(p = dlmemalign(align, ROUNDUP(size, 8) + 16))) return NULL; - s = (char *)SHADOW((intptr_t)p - 16); - q = size / 8; - r = size % 8; - *s++ = underrun; - *s++ = underrun; - memset(s, 0, q); - s += q; - if (r) *s++ = r; - *s++ = overrun; - *s++ = overrun; - return p; -} - -static void __asan_deallocate(char *p, int kind) { - char *s; - s = (char *)SHADOW((intptr_t)p); - if ((*s < 0 && *s != kAsanHeapOverrun) || *s >= 8) { - __asan_report_deallocate_fault(p, *s); - } - memset(s, kind, dlmalloc_usable_size(p) >> 3); - dlfree(__asan_morgue_add(p)); -} - -static void __asan_poison_redzone(intptr_t addr, size_t size, size_t redsize, - int kind) { - char *s; - intptr_t p; - size_t a, b, w; - w = (intptr_t)addr & 7; - p = (intptr_t)addr - w; - a = w + size; - b = w + redsize; - s = (char *)SHADOW(p + a); - if (a & 7) *s++ = a & 7; - memset(s, kind, (b - ROUNDUP(a, 8)) >> 3); -} - -static size_t __asan_malloc_usable_size(const void *vp) { - char *s; - size_t n; - for (n = 0, s = (char *)SHADOW((intptr_t)vp);; ++s) { - if (!*s) { - n += 8; - } else if (*s > 0) { - n += *s & 7; - } else { - break; - } - } - return n; -} - -static void __asan_free(void *p) { - if (!p) return; - __asan_deallocate(p, kAsanHeapFree); -} - -static void *__asan_memalign(size_t align, size_t size) { - return __asan_allocate(align, size, kAsanHeapUnderrun, kAsanHeapOverrun); -} - -static void *__asan_malloc(size_t size) { - return __asan_memalign(16, size); -} - -static void *__asan_calloc(size_t n, size_t m) { - char *p; - size_t size; - if (__builtin_mul_overflow(n, m, &size)) size = -1; - if ((p = __asan_malloc(size))) memset(p, 0, size); - return p; -} - -static void *__asan_realloc(void *p, size_t n) { - char *p2; - if (p) { - if (n) { - if ((p2 = __asan_malloc(n))) { - memcpy(p2, p, min(n, dlmalloc_usable_size(p))); - __asan_deallocate(p, kAsanRelocated); - } - } else { - __asan_free(p); - p2 = NULL; - } - } else { - p2 = __asan_malloc(n); - } - return p2; -} - -static void *__asan_valloc(size_t n) { - return __asan_memalign(PAGESIZE, n); -} - -static void *__asan_pvalloc(size_t n) { - return __asan_valloc(ROUNDUP(n, PAGESIZE)); -} - -static int __asan_malloc_trim(size_t pad) { - __asan_morgue_flush(); - return dlmalloc_trim(pad); -} - -void __asan_register_globals(struct AsanGlobal g[], int n) { - unsigned i; - for (i = 0; i < n; ++i) { - __asan_poison_redzone((intptr_t)g[i].addr, g[i].size, - g[i].size_with_redzone, kAsanGlobalOverrun); - } -} - -void __asan_unregister_globals(struct AsanGlobal g[], int n) { - unsigned i; - intptr_t a, b; - for (i = 0; i < n; ++i) { - a = ROUNDUP((intptr_t)g[i].addr, 8); - b = ROUNDDOWN((intptr_t)g[i].addr + g[i].size_with_redzone, 8); - if (b > a) { - memset((char *)SHADOW(a), kAsanGlobalUnregistered, (b - a) >> 3); - } - } -} - -void *__asan_stack_malloc(size_t size, int classid) { - return __asan_allocate(32, size, kAsanStackUnderrun, kAsanStackOverrun); -} - -void __asan_stack_free(char *p, size_t size, int classid) { - dlfree(p); -} - -void __asan_report_load_n(uint8_t *addr, int size) { - __asan_report_memory_fault(addr, size, "load"); -} - -void __asan_report_store_n(uint8_t *addr, int size) { - __asan_report_memory_fault(addr, size, "store"); -} - -void __asan_poison_stack_memory(uintptr_t p, size_t n) { - memset((char *)SHADOW(p), kAsanUnscoped, n >> 3); - if (n & 7) *(char *)SHADOW(p + n) = 8 - (n & 7); -} - -void __asan_unpoison_stack_memory(uintptr_t p, size_t n) { - memset((char *)SHADOW(p), 0, n >> 3); - if (n & 7) *(char *)SHADOW(p + n) = n & 7; -} - -void __asan_alloca_poison(intptr_t addr, size_t size) { - __asan_poison_redzone(addr, size, size + 32, kAsanAllocaOverrun); -} - -void __asan_allocas_unpoison(uintptr_t top, uintptr_t bottom) { - memset((char *)SHADOW(top), 0, (bottom - top) >> 3); -} - -void *__asan_addr_is_in_fake_stack(void *fakestack, void *addr, void **beg, - void **end) { - return NULL; -} - -void *__asan_get_current_fake_stack(void) { - return NULL; -} - -void __asan_install_malloc_hooks(void) { - HOOK(hook$free, __asan_free); - HOOK(hook$malloc, __asan_malloc); - HOOK(hook$calloc, __asan_calloc); - HOOK(hook$valloc, __asan_valloc); - HOOK(hook$pvalloc, __asan_pvalloc); - HOOK(hook$realloc, __asan_realloc); - HOOK(hook$memalign, __asan_memalign); - HOOK(hook$malloc_trim, __asan_malloc_trim); - HOOK(hook$malloc_usable_size, __asan_malloc_usable_size); -} - -static bool __asan_is_mapped(int x) { - int i = FindMemoryInterval(&_mmi, x); - return i < _mmi.i && x >= _mmi.p[i].x && x <= _mmi.p[i].y; -} - -void __asan_map_shadow(void *p, size_t n) { - int i, x, a, b; - struct DirectMap sm; - a = SHADOW((uintptr_t)p) >> 16; - b = ROUNDUP(SHADOW(ROUNDUP((uintptr_t)p + n, 8)), 1 << 16) >> 16; - for (; a < b; ++a) { - if (!__asan_is_mapped(a)) { - sm = __mmap((void *)((uintptr_t)a << 16), 1 << 16, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); - if (sm.addr == MAP_FAILED || - TrackMemoryInterval(&_mmi, a, a, sm.maphandle, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED) == -1) { - abort(); - } - } - } -} - -static char *__asan_get_stack_base(void) { - uintptr_t rsp; - asm("mov\t%%rsp,%0" : "=r"(rsp)); - return (char *)ROUNDDOWN(ROUNDDOWN(rsp, STACKSIZE), FRAMESIZE); -} - -static textstartup size_t __asan_get_auxv_size(intptr_t *auxv) { - unsigned i; - for (i = 0;; i += 2) { - if (!auxv[i]) break; - } - return (i + 2) * sizeof(intptr_t); -} - -static textstartup void __asan_shadow_string_list(char **list) { - for (; *list; ++list) { - __asan_map_shadow(*list, strlen(*list) + 1); - } -} - -textstartup void __asan_init(int argc, char **argv, char **envp, - intptr_t *auxv) { - static bool once; - if (once) return; - __asan_map_shadow(_base, _end - _base); - __asan_map_shadow(__asan_get_stack_base(), STACKSIZE); - __asan_shadow_string_list(argv); - __asan_shadow_string_list(envp); - __asan_map_shadow(auxv, __asan_get_auxv_size(auxv)); - __asan_install_malloc_hooks(); -} - -static textstartup void __asan_ctor(void) { - __cxa_atexit(__asan_morgue_flush, NULL, NULL); -} - -const void *const g_asan_ctor[] initarray = {__asan_ctor}; diff --git a/libc/log/asan.internal.h b/libc/log/asan.internal.h deleted file mode 100644 index 6bfc4110..00000000 --- a/libc/log/asan.internal.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_LOG_ASAN_H_ -#define COSMOPOLITAN_LIBC_LOG_ASAN_H_ - -#define kAsanScale 3 -#define kAsanMagic 0x7fff8000 -#define kAsanHeapFree -1 -#define kAsanStackFree -2 -#define kAsanRelocated -3 -#define kAsanHeapUnderrun -4 -#define kAsanHeapOverrun -5 -#define kAsanGlobalOverrun -6 -#define kAsanGlobalUnregistered -7 -#define kAsanStackUnderrun -8 -#define kAsanStackOverrun -9 -#define kAsanAllocaOverrun -10 -#define kAsanUnscoped -11 - -#define SHADOW(x) (((x) >> kAsanScale) + kAsanMagic) - -void __asan_map_shadow(void *, size_t); - -#endif /* COSMOPOLITAN_LIBC_LOG_ASAN_H_ */ diff --git a/libc/log/backtrace2.c b/libc/log/backtrace2.c index f2e6eb44..eb34bc68 100644 --- a/libc/log/backtrace2.c +++ b/libc/log/backtrace2.c @@ -21,10 +21,12 @@ #include "libc/bits/safemacros.h" #include "libc/bits/weaken.h" #include "libc/calls/calls.h" +#include "libc/calls/sigbits.h" #include "libc/dce.h" #include "libc/errno.h" #include "libc/fmt/conv.h" #include "libc/fmt/fmt.h" +#include "libc/fmt/itoa.h" #include "libc/log/backtrace.internal.h" #include "libc/log/log.h" #include "libc/nexgen32e/gc.internal.h" @@ -33,9 +35,10 @@ #include "libc/str/str.h" #include "libc/sysv/consts/fileno.h" #include "libc/sysv/consts/o.h" +#include "libc/sysv/consts/sig.h" #define kBacktraceMaxFrames 128 -#define kBacktraceBufSize ((kBacktraceMaxFrames - 1) * (16 + 1)) +#define kBacktraceBufSize ((kBacktraceMaxFrames - 1) * (18 + 1)) static int PrintBacktraceUsingAddr2line(int fd, const struct StackFrame *bp) { ssize_t got; @@ -43,7 +46,9 @@ static int PrintBacktraceUsingAddr2line(int fd, const struct StackFrame *bp) { size_t i, j, gi; int ws, pid, pipefds[2]; struct Garbages *garbage; + sigset_t chldmask, savemask; const struct StackFrame *frame; + struct sigaction ignore, saveint, savequit; const char *debugbin, *p1, *p2, *p3, *addr2line; char buf[kBacktraceBufSize], *argv[kBacktraceMaxFrames]; if (IsOpenbsd()) return -1; @@ -66,12 +71,25 @@ static int PrintBacktraceUsingAddr2line(int fd, const struct StackFrame *bp) { --gi; } while ((addr = garbage->p[gi].ret) == weakaddr("__gc")); } - argv[i++] = &buf[j]; - j += snprintf(&buf[j], 17, "%#x", addr - 1) + 1; + argv[i++] = buf + j; + buf[j++] = '0'; + buf[j++] = 'x'; + j += uint64toarray_radix16(addr - 1, buf + j) + 1; } argv[i++] = NULL; + ignore.sa_flags = 0; + ignore.sa_handler = SIG_IGN; + sigemptyset(&ignore.sa_mask); + sigaction(SIGINT, &ignore, &saveint); + sigaction(SIGQUIT, &ignore, &savequit); + sigemptyset(&chldmask); + sigaddset(&chldmask, SIGCHLD); + sigprocmask(SIG_BLOCK, &chldmask, &savemask); pipe(pipefds); if (!(pid = vfork())) { + sigaction(SIGINT, &saveint, NULL); + sigaction(SIGQUIT, &savequit, NULL); + sigprocmask(SIG_SETMASK, &savemask, NULL); dup2(pipefds[1], 1); close(pipefds[0]); close(pipefds[1]); @@ -106,6 +124,9 @@ static int PrintBacktraceUsingAddr2line(int fd, const struct StackFrame *bp) { if (errno == EINTR) continue; return -1; } + sigaction(SIGINT, &saveint, NULL); + sigaction(SIGQUIT, &savequit, NULL); + sigprocmask(SIG_SETMASK, &savemask, NULL); if (WIFEXITED(ws) && !WEXITSTATUS(ws)) { return 0; } else { diff --git a/libc/log/checkfail.c b/libc/log/checkfail.c index 37caa6e6..8e5a010e 100644 --- a/libc/log/checkfail.c +++ b/libc/log/checkfail.c @@ -56,10 +56,10 @@ relegated void __check_fail(const char *suffix, const char *opstr, gethostname(hostname, sizeof(hostname)); (dprintf)(STDERR_FILENO, - "check failed on %s pid %d\n" - "\tCHECK_%s(%s, %s);\n" - "\t\t → %#lx (%s)\n" - "\t\t%s %#lx (%s)\n", + "check failed on %s pid %d\r\n" + "\tCHECK_%s(%s, %s);\r\n" + "\t\t → %#lx (%s)\r\n" + "\t\t%s %#lx (%s)\r\n", hostname, getpid(), sufbuf, wantstr, gotstr, want, wantstr, opstr, got, gotstr); @@ -68,19 +68,19 @@ relegated void __check_fail(const char *suffix, const char *opstr, va_start(va, fmt); (vdprintf)(STDERR_FILENO, fmt, va); va_end(va); - (dprintf)(STDERR_FILENO, "\n"); + (dprintf)(STDERR_FILENO, "\r\n"); } - (dprintf)(STDERR_FILENO, "\t%s\n\t%s%s%s%s\n", strerror(lasterr), SUBTLE, + (dprintf)(STDERR_FILENO, "\t%s\r\n\t%s%s%s%s\r\n", strerror(lasterr), SUBTLE, getauxval(AT_EXECFN), g_argc > 1 ? " \\" : "", RESET); for (i = 1; i < g_argc; ++i) { - (dprintf)(STDERR_FILENO, "\t\t%s%s\n", g_argv[i], + (dprintf)(STDERR_FILENO, "\t\t%s%s\r\n", g_argv[i], i < g_argc - 1 ? " \\" : ""); } if (!IsTiny() && lasterr == ENOMEM) { - (dprintf)(STDERR_FILENO, "\n"); + (dprintf)(STDERR_FILENO, "\r\n"); PrintMemoryIntervals(STDERR_FILENO, &_mmi); } diff --git a/libc/log/checkfail_ndebug.c b/libc/log/checkfail_ndebug.c index a3a1a18c..b232a73e 100644 --- a/libc/log/checkfail_ndebug.c +++ b/libc/log/checkfail_ndebug.c @@ -46,5 +46,5 @@ relegated void ___check_fail_ndebug(uint64_t want, uint64_t got, __print(bx, uint64toarray_radix16(got, bx)); __print_string(" ("); __print(bx, int64toarray_radix10(lasterr, bx)); - __print_string(")\n"); + __print_string(")\r\n"); } diff --git a/libc/log/die.c b/libc/log/die.c index d25e3c18..29216b49 100644 --- a/libc/log/die.c +++ b/libc/log/die.c @@ -17,12 +17,12 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/bits/bits.h" +#include "libc/bits/weaken.h" +#include "libc/dce.h" #include "libc/log/backtrace.internal.h" #include "libc/log/log.h" -#include "libc/runtime/internal.h" +#include "libc/runtime/runtime.h" #include "libc/stdio/stdio.h" -#include "libc/sysv/consts/exit.h" -#include "libc/sysv/consts/fileno.h" /** * Aborts process after printing a backtrace. @@ -31,15 +31,14 @@ */ relegated wontreturn void __die(void) { static bool once; - if (!once) { - once = true; + if (cmpxchg(&once, false, true)) { + if (weaken(fflush)) { + weaken(fflush)(NULL); + } if (!IsTiny()) { if (IsDebuggerPresent(false)) DebugBreak(); - ShowBacktrace(STDERR_FILENO, NULL); + ShowBacktrace(2, NULL); } - exit(EXIT_FAILURE); - unreachable; } - abort(); - unreachable; + _exit(77); } diff --git a/libc/log/getttysize.c b/libc/log/getttysize.c index 47484cfb..a9167231 100644 --- a/libc/log/getttysize.c +++ b/libc/log/getttysize.c @@ -34,7 +34,7 @@ * @returns -1 on error or something else on success */ int getttysize(int fd, struct winsize *out) { - if (isterminalinarticulate()) { + if (IsTerminalInarticulate()) { out->ws_col = strtoimax(firstnonnull(getenv("COLUMNS"), "80"), NULL, 0); out->ws_row = strtoimax(firstnonnull(getenv("ROWS"), "40"), NULL, 0); out->ws_xpixel = 0; diff --git a/libc/log/isrunningundermake.c b/libc/log/isrunningundermake.c index 7ef512a6..d200b3af 100644 --- a/libc/log/isrunningundermake.c +++ b/libc/log/isrunningundermake.c @@ -22,4 +22,6 @@ /** * Returns true if current process was spawned by GNU Make. */ -bool isrunningundermake(void) { return !!getenv("MAKEFLAGS"); } +bool IsRunningUnderMake(void) { + return !!getenv("MAKEFLAGS"); +} diff --git a/libc/log/isterminalinarticulate.c b/libc/log/isterminalinarticulate.c index 5983575e..b1397135 100644 --- a/libc/log/isterminalinarticulate.c +++ b/libc/log/isterminalinarticulate.c @@ -24,6 +24,6 @@ /** * Checks if we're probably running inside Emacs. */ -bool isterminalinarticulate(void) { +bool IsTerminalInarticulate(void) { return strcmp(nulltoempty(getenv("TERM")), "dumb") == 0; } diff --git a/libc/log/log.h b/libc/log/log.h index a5d68d64..c92f2977 100644 --- a/libc/log/log.h +++ b/libc/log/log.h @@ -39,7 +39,7 @@ void meminfo(int); /* shows malloc statistics &c. */ void memsummary(int); /* light version of same thing */ uint16_t getttycols(uint16_t); int getttysize(int, struct winsize *) paramsnonnull(); -bool isterminalinarticulate(void) nosideeffect; +bool IsTerminalInarticulate(void) nosideeffect; char *commandvenv(const char *, const char *) nodiscard; const char *GetAddr2linePath(void); const char *GetGdbPath(void); @@ -47,7 +47,7 @@ const char *GetGdbPath(void); void showcrashreports(void); void callexitontermination(struct sigset *); bool32 IsDebuggerPresent(bool); -bool isrunningundermake(void); +bool IsRunningUnderMake(void); /*───────────────────────────────────────────────────────────────────────────│─╗ │ cosmopolitan § liblog » logging ─╬─│┼ diff --git a/libc/log/log.mk b/libc/log/log.mk index 3cfb000f..f0aa754f 100644 --- a/libc/log/log.mk +++ b/libc/log/log.mk @@ -58,15 +58,21 @@ $(LIBC_LOG_A).pkg: \ $(LIBC_LOG_A_OBJS) \ $(foreach x,$(LIBC_LOG_A_DIRECTDEPS),$($(x)_A).pkg) -$(LIBC_LOG_A_OBJS): \ +o/$(MODE)/libc/log/attachdebugger.o \ +o/$(MODE)/libc/log/backtrace2.o \ +o/$(MODE)/libc/log/backtrace3.o \ +o/$(MODE)/libc/log/checkaligned.o \ +o/$(MODE)/libc/log/checkfail.o \ +o/$(MODE)/libc/log/checkfail_ndebug.o \ +o/$(MODE)/libc/log/getsymboltable.o \ +o/$(MODE)/libc/log/oncrash.o \ +o/$(MODE)/libc/log/onkill.o \ +o/$(MODE)/libc/log/startfatal.o \ +o/$(MODE)/libc/log/startfatal_ndebug.o \ +o/$(MODE)/libc/log/ubsan.o \ +o/$(MODE)/libc/log/die.o: \ OVERRIDE_CFLAGS += \ - $(NO_MAGIC) \ - -fwrapv - -# ifeq (,$(MODE)) -# LIBC_LOG_ASAN = o/$(MODE)/libc/log/asan.o -# endif -LIBC_LOG_ASAN_A = o/$(MODE)/libc/log/log.a + $(NO_MAGIC) LIBC_LOG_LIBS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x))) LIBC_LOG_SRCS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x)_SRCS)) diff --git a/libc/log/oncrash.c b/libc/log/oncrash.c index ecaff714..9a184d78 100644 --- a/libc/log/oncrash.c +++ b/libc/log/oncrash.c @@ -182,8 +182,9 @@ relegated static void ShowCrashReport(int err, int fd, int sig, write(fd, "\r\n", 2); for (i = 0; i < g_argc; ++i) { write(fd, g_argv[i], strlen(g_argv[i])); - write(fd, "\r\n", 2); + write(fd, " ", 1); } + write(fd, "\r\n", 2); } relegated static void RestoreDefaultCrashSignalHandlers(void) { @@ -221,9 +222,9 @@ relegated void __oncrash(int sig, struct siginfo *si, ucontext_t *ctx) { rip = ctx ? ctx->uc_mcontext.rip : 0; if ((gdbpid = IsDebuggerPresent(true))) { DebugBreak(); - } else if (isterminalinarticulate() || isrunningundermake()) { + } else if (IsTerminalInarticulate() || IsRunningUnderMake()) { gdbpid = -1; - } else { + } else if (FindDebugBinary()) { RestoreDefaultCrashSignalHandlers(); gdbpid = attachdebugger(((sig == SIGTRAP || sig == SIGQUIT) && diff --git a/libc/nexgen32e/kcp437.S b/libc/nexgen32e/kcp437.S index 86aae89c..0379adc1 100644 --- a/libc/nexgen32e/kcp437.S +++ b/libc/nexgen32e/kcp437.S @@ -90,6 +90,6 @@ kCp437: .short 0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x03bc,0x03c4 #e0:αßΓπΣσμτ .short 0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229 #e8:ΦΘΩδ∞φε∩ .short 0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248 #f0:≡±≥≤⌠⌡÷≈ -.short 0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x03bb #f8:°∙·√ⁿ²■λ +.short 0x00b0,0x2219,0x00d7,0x221a,0x207f,0x00b2,0x25a0,0x03bb #f8:°∙×√ⁿ²■λ .endobj kCp437,globl .previous diff --git a/libc/nexgen32e/memcpy.S b/libc/nexgen32e/memcpy.S index 91840cbb..bf0dbd9d 100644 --- a/libc/nexgen32e/memcpy.S +++ b/libc/nexgen32e/memcpy.S @@ -40,10 +40,9 @@ / @return original rdi copied to rax / @mode long / @asyncsignalsafe - .align 16 - .source __FILE__ memcpy: mov %rdi,%rax / 𝑠𝑙𝑖𝑑𝑒 + .align 16 .endfn memcpy,globl / Copies memory w/ minimal impact ABI. @@ -53,7 +52,6 @@ memcpy: mov %rdi,%rax / @param rdx is number of bytes / @clob flags,rcx,xmm3,xmm4 / @mode long - .align 16 MemCpy: .leafprologue .profilable mov $.Lmemcpytab.ro.size,%ecx @@ -141,6 +139,7 @@ MemCpy: .leafprologue pxor %xmm3,%xmm3 jmp .L0 .endfn MemCpy,globl,hidden + .source __FILE__ .initro 300,_init_memcpy memcpytab.ro: diff --git a/libc/nexgen32e/memset.S b/libc/nexgen32e/memset.S index c892e853..04c025ef 100644 --- a/libc/nexgen32e/memset.S +++ b/libc/nexgen32e/memset.S @@ -23,7 +23,6 @@ #include "libc/nexgen32e/x86feature.h" #include "libc/nexgen32e/macros.h" #include "libc/macros.h" -.source __FILE__ / Sets memory. / @@ -34,7 +33,8 @@ / @mode long / @asyncsignalsafe memset: mov %rdi,%rax -/ fallthrough +/ 𝑠𝑙𝑖𝑑𝑒 + .align 16 .endfn memset,globl / Sets memory w/ minimal-impact ABI. @@ -98,6 +98,7 @@ MemSet: .leafprologue pop %rax jmp .L0 .endfn MemSet,globl,hidden + .source __FILE__ .rodata.cst8 .Lb8: .quad 0x0101010101010101 diff --git a/libc/runtime/executive.S b/libc/runtime/cosmo.S similarity index 92% rename from libc/runtime/executive.S rename to libc/runtime/cosmo.S index ba599c69..93bd6e73 100644 --- a/libc/runtime/executive.S +++ b/libc/runtime/cosmo.S @@ -25,22 +25,29 @@ .text.startup .source __FILE__ -/ Stack frame that owns process from spawn to exit. +/ Cosmopolitan runtime. / / @param edi is argc / @param rsi is argv / @param rdx is environ / @param rcx is auxv / @noreturn -_executive: - push %rbp +cosmo: push %rbp mov %rsp,%rbp ezlea _base,bx mov %edi,%r12d mov %rsi,%r13 mov %rdx,%r14 mov %rcx,%r15 - call _spawn +#ifdef __FAST_MATH__ + call __fast_math +#endif + call _init + call _construct +#if !IsTrustworthy() + mov $PROT_READ,%edi + call _piro +#endif mov %r12d,%edi mov %r13,%rsi mov %r14,%rdx @@ -49,7 +56,7 @@ _executive: call main xchg %eax,%edi call exit - .endfn _executive,weak,hidden + .endfn cosmo,weak,hidden ud2 #ifdef __PG__ diff --git a/libc/runtime/finddebugbinary.c b/libc/runtime/finddebugbinary.c index eb8fb05f..29dc83e6 100644 --- a/libc/runtime/finddebugbinary.c +++ b/libc/runtime/finddebugbinary.c @@ -36,6 +36,7 @@ const char *FindDebugBinary(void) { char buf[2][PATH_MAX]; static char res[PATH_MAX]; const char *bins[4], *pwd; + if (res[0]) return res; bins[0] = program_invocation_name; bins[1] = (const char *)getauxval(AT_EXECFN); pwd = emptytonull(getenv("PWD")); @@ -59,6 +60,7 @@ const char *FindDebugBinary(void) { return res; } } + res[0] = '\0'; errno = ENOENT; return NULL; } diff --git a/libc/runtime/internal.h b/libc/runtime/internal.h index 11f0323b..9b93d566 100644 --- a/libc/runtime/internal.h +++ b/libc/runtime/internal.h @@ -19,7 +19,7 @@ extern hidden void *g_stacktop; void _init(void) hidden; void _piro(int) hidden; void *__cxa_finalize(void *) hidden; -void _executive(int, char **, char **, long (*)[2]) hidden wontreturn; +void cosmo(int, char **, char **, long (*)[2]) hidden wontreturn; void __stack_chk_fail(void) wontreturn relegated; void __stack_chk_fail_local(void) wontreturn relegated hidden; void _jmpstack(void *, void *, ...) hidden wontreturn; diff --git a/libc/runtime/memtrack.h b/libc/runtime/memtrack.h index 0d1d8cce..45a93e84 100644 --- a/libc/runtime/memtrack.h +++ b/libc/runtime/memtrack.h @@ -23,7 +23,7 @@ COSMOPOLITAN_C_START_ #define kFixedmapStart MEMTRACK_ADDRESS(_kFixedmapStart, 0x40000000) struct MemoryIntervals { - int i; + long i; struct MemoryInterval { int x; int y; diff --git a/libc/runtime/mmap.c b/libc/runtime/mmap.c index 381df6f1..e375eb25 100644 --- a/libc/runtime/mmap.c +++ b/libc/runtime/mmap.c @@ -21,7 +21,7 @@ #include "libc/calls/calls.h" #include "libc/calls/internal.h" #include "libc/dce.h" -#include "libc/log/asan.internal.h" +#include "libc/intrin/asan.internal.h" #include "libc/macros.h" #include "libc/rand/rand.h" #include "libc/runtime/directmap.h" @@ -94,7 +94,7 @@ void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) { abort(); } if (weaken(__asan_map_shadow)) { - weaken(__asan_map_shadow)(dm.addr, size); + weaken(__asan_map_shadow)((uintptr_t)dm.addr, size); } return dm.addr; } diff --git a/libc/runtime/runtime.mk b/libc/runtime/runtime.mk index fca913f7..fa208100 100644 --- a/libc/runtime/runtime.mk +++ b/libc/runtime/runtime.mk @@ -56,7 +56,23 @@ $(LIBC_RUNTIME_A).pkg: \ $(LIBC_RUNTIME_A_OBJS) \ $(foreach x,$(LIBC_RUNTIME_A_DIRECTDEPS),$($(x)_A).pkg) -$(LIBC_RUNTIME_A_OBJS): \ +o/$(MODE)/libc/runtime/abort-nt.o \ +o/$(MODE)/libc/runtime/assertfail.o \ +o/$(MODE)/libc/runtime/memtrack.o \ +o/$(MODE)/libc/runtime/memtracknt.o \ +o/$(MODE)/libc/runtime/findmemoryinterval.o \ +o/$(MODE)/libc/runtime/arememoryintervalsok.o \ +o/$(MODE)/libc/runtime/isheap.o \ +o/$(MODE)/libc/runtime/directmap.o \ +o/$(MODE)/libc/runtime/directmapnt.o \ +o/$(MODE)/libc/runtime/stackchkfail.o \ +o/$(MODE)/libc/runtime/stackchkfaillocal.o \ +o/$(MODE)/libc/runtime/hook.greg.o \ +o/$(MODE)/libc/runtime/print.greg.o \ +o/$(MODE)/libc/runtime/ftrace.greg.o \ +o/$(MODE)/libc/runtime/getdosargv.o \ +o/$(MODE)/libc/runtime/getdosenviron.o \ +o/$(MODE)/libc/runtime/winmain.greg.o: \ OVERRIDE_CFLAGS += \ $(NO_MAGIC) diff --git a/libc/runtime/winmain.greg.c b/libc/runtime/winmain.greg.c index 1e6cbd77..97e7a94e 100644 --- a/libc/runtime/winmain.greg.c +++ b/libc/runtime/winmain.greg.c @@ -49,8 +49,6 @@ * TODO: How can we ensure we never overlap with KERNEL32.DLL? */ -#define WINSTACK 0x100000 - struct WinArgs { char *argv[4096]; char *envp[4096]; @@ -109,7 +107,7 @@ static textwindows wontreturn void WinMainNew(void) { NormalizeCmdExe(); *(/*unconst*/ int *)&__hostos = WINDOWS; addr = NtGetVersion() < kNtVersionWindows10 ? 0xff00000 : 0x777000000000; - size = ROUNDUP(WINSTACK + sizeof(struct WinArgs), FRAMESIZE); + size = ROUNDUP(STACKSIZE + sizeof(struct WinArgs), FRAMESIZE); _mmi.p[0].h = __mmap$nt((char *)addr, size, PROT_READ | PROT_WRITE | PROT_EXEC, -1, 0) .maphandle; @@ -130,8 +128,7 @@ static textwindows wontreturn void WinMainNew(void) { FreeEnvironmentStrings(env16); auxv[0][0] = pushpop(0L); auxv[0][1] = pushpop(0L); - _jmpstack((char *)addr + WINSTACK, _executive, count, wa->argv, wa->envp, - auxv); + _jmpstack((char *)addr + STACKSIZE, cosmo, count, wa->argv, wa->envp, auxv); } /** diff --git a/libc/nexgen32e/bsf.c b/libc/str/bsf.c similarity index 100% rename from libc/nexgen32e/bsf.c rename to libc/str/bsf.c diff --git a/libc/nexgen32e/bsfl.c b/libc/str/bsfl.c similarity index 100% rename from libc/nexgen32e/bsfl.c rename to libc/str/bsfl.c diff --git a/libc/nexgen32e/bsfll.c b/libc/str/bsfll.c similarity index 100% rename from libc/nexgen32e/bsfll.c rename to libc/str/bsfll.c diff --git a/libc/nexgen32e/bsr.c b/libc/str/bsr.c similarity index 100% rename from libc/nexgen32e/bsr.c rename to libc/str/bsr.c diff --git a/libc/nexgen32e/bsrl.c b/libc/str/bsrl.c similarity index 100% rename from libc/nexgen32e/bsrl.c rename to libc/str/bsrl.c diff --git a/libc/nexgen32e/bsrll.c b/libc/str/bsrll.c similarity index 100% rename from libc/nexgen32e/bsrll.c rename to libc/str/bsrll.c diff --git a/libc/nexgen32e/crc32.S b/libc/str/crc32.S similarity index 100% rename from libc/nexgen32e/crc32.S rename to libc/str/crc32.S diff --git a/libc/nexgen32e/crc32c-pure.c b/libc/str/crc32c-pure.c similarity index 100% rename from libc/nexgen32e/crc32c-pure.c rename to libc/str/crc32c-pure.c diff --git a/libc/nexgen32e/crc32c-sse42.c b/libc/str/crc32c-sse42.c similarity index 100% rename from libc/nexgen32e/crc32c-sse42.c rename to libc/str/crc32c-sse42.c diff --git a/libc/nexgen32e/crc32c.S b/libc/str/crc32c.S similarity index 100% rename from libc/nexgen32e/crc32c.S rename to libc/str/crc32c.S diff --git a/libc/nexgen32e/crc32z.c b/libc/str/crc32z.c similarity index 100% rename from libc/nexgen32e/crc32z.c rename to libc/str/crc32z.c diff --git a/libc/nexgen32e/ctz.c b/libc/str/ctz.c similarity index 100% rename from libc/nexgen32e/ctz.c rename to libc/str/ctz.c diff --git a/libc/nexgen32e/djbsort.c b/libc/str/djbsort.c similarity index 100% rename from libc/nexgen32e/djbsort.c rename to libc/str/djbsort.c diff --git a/libc/nexgen32e/insertionsort.greg.c b/libc/str/insertionsort.greg.c similarity index 100% rename from libc/nexgen32e/insertionsort.greg.c rename to libc/str/insertionsort.greg.c diff --git a/libc/str/memccpy.c b/libc/str/memccpy.c index 5276596c..1276d634 100644 --- a/libc/str/memccpy.c +++ b/libc/str/memccpy.c @@ -45,7 +45,8 @@ */ void *memccpy(void *d, const void *s, int c, size_t n) { const char *p, *pe; - if ((pe = memchr((p = s), c, n))) { + p = s; + if ((pe = memchr(p, c, n))) { return mempcpy(d, s, pe - p + 1); } else { memcpy(d, s, n); diff --git a/libc/str/stpcpy.c b/libc/str/stpcpy.c index 4b60a32e..7d25a864 100644 --- a/libc/str/stpcpy.c +++ b/libc/str/stpcpy.c @@ -20,26 +20,8 @@ #include "libc/intrin/pmovmskb.h" #include "libc/str/str.h" -/** - * Copies bytes from 𝑠 to 𝑑 until a NUL is encountered. - * - * @param 𝑑 is destination memory - * @param 𝑠 is a NUL-terminated string - * @note 𝑑 and 𝑠 can't overlap - * @return pointer to nul byte - * @see strcpy(), memccpy() - * @asyncsignalsafe - */ -char *stpcpy(char *d, const char *s) { - size_t i; +static noasan size_t stpcpy$sse2(char *d, const char *s, size_t i) { uint8_t v1[16], v2[16], vz[16]; - i = 0; - while (((uintptr_t)(s + i) & 15)) { - if (!(d[i] = s[i])) { - return d + i; - } - ++i; - } for (;;) { memset(vz, 0, 16); memcpy(v1, s + i, 16); @@ -51,6 +33,26 @@ char *stpcpy(char *d, const char *s) { break; } } + return i; +} + +/** + * Copies bytes from 𝑠 to 𝑑 until a NUL is encountered. + * + * @param 𝑑 is destination memory + * @param 𝑠 is a NUL-terminated string + * @note 𝑑 and 𝑠 can't overlap + * @return pointer to nul byte + * @asyncsignalsafe + */ +char *stpcpy(char *d, const char *s) { + size_t i; + for (i = 0; (uintptr_t)(s + i) & 15; ++i) { + if (!(d[i] = s[i])) { + return d + i; + } + } + i = stpcpy$sse2(d, s, i); for (;;) { if (!(d[i] = s[i])) { return d + i; diff --git a/libc/str/str.h b/libc/str/str.h index 81d3e6e7..b2693106 100644 --- a/libc/str/str.h +++ b/libc/str/str.h @@ -90,6 +90,7 @@ void *memeqmask(void *, const void *, const void *, size_t) memcpyesque; size_t strlen(const char *) strlenesque; size_t strnlen(const char *, size_t) strlenesque; size_t strnlen_s(const char *, size_t); +size_t strlen$pure(const char *) strlenesque; char *strchr(const char *, int) strlenesque; char *index(const char *, int) strlenesque; void *memchr(const void *, int, size_t) strlenesque; @@ -360,6 +361,17 @@ char *strsignal(int) returnsnonnull libcesque; }) #endif /* hosted/sse2/unbloat */ +#ifdef __FSANITIZE_ADDRESS__ +/*───────────────────────────────────────────────────────────────────────────│─╗ +│ cosmopolitan § strings » address sanitizer ─╬─│┼ +╚────────────────────────────────────────────────────────────────────────────│*/ + +#ifdef strlen +#undef strlen +#endif +#define strlen(s) strlen$pure(s) + +#endif /* __FSANITIZE_ADDRESS__ */ #endif /* __GNUC__ && !__STRICT_ANSI__ */ COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/libc/str/str.mk b/libc/str/str.mk index 87d8cf66..6f9927c6 100644 --- a/libc/str/str.mk +++ b/libc/str/str.mk @@ -42,8 +42,8 @@ $(LIBC_STR_A).pkg: \ $(LIBC_STR_A_OBJS) \ $(foreach x,$(LIBC_STR_A_DIRECTDEPS),$($(x)_A).pkg) -o/$(MODE)/libc/str/memmem.o: \ - OVERRIDE_CPPFLAGS += \ +o/$(MODE)/libc/str/memmem.o: \ + OVERRIDE_CPPFLAGS += \ -DSTACK_FRAME_UNLIMITED LIBC_STR_LIBS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x))) diff --git a/libc/str/strcpy.c b/libc/str/strcpy.c index 723caa33..14fddfc1 100644 --- a/libc/str/strcpy.c +++ b/libc/str/strcpy.c @@ -20,26 +20,8 @@ #include "libc/intrin/pmovmskb.h" #include "libc/str/str.h" -/** - * Copies bytes from 𝑠 to 𝑑 until a NUL is encountered. - * - * @param 𝑑 is destination memory - * @param 𝑠 is a NUL-terminated string - * @note 𝑑 and 𝑠 can't overlap - * @return original dest - * @see memccpy() - * @asyncsignalsafe - */ -char *strcpy(char *d, const char *s) { - size_t i; +static noasan size_t strcpy$sse2(char *d, const char *s, size_t i) { uint8_t v1[16], v2[16], vz[16]; - i = 0; - while (((uintptr_t)(s + i) & 15)) { - if (!(d[i] = s[i])) { - return d; - } - ++i; - } for (;;) { memset(vz, 0, 16); memcpy(v1, s + i, 16); @@ -51,6 +33,26 @@ char *strcpy(char *d, const char *s) { break; } } + return i; +} + +/** + * Copies bytes from 𝑠 to 𝑑 until a NUL is encountered. + * + * @param 𝑑 is destination memory + * @param 𝑠 is a NUL-terminated string + * @note 𝑑 and 𝑠 can't overlap + * @return original dest + * @asyncsignalsafe + */ +char *strcpy(char *d, const char *s) { + size_t i; + for (i = 0; (uintptr_t)(s + i) & 15; ++i) { + if (!(d[i] = s[i])) { + return d; + } + } + i = strcpy$sse2(d, s, i); for (;;) { if (!(d[i] = s[i])) { return d; diff --git a/libc/str/strlen-pure.c b/libc/str/strlen-pure.c new file mode 100644 index 00000000..cf6d698c --- /dev/null +++ b/libc/str/strlen-pure.c @@ -0,0 +1,50 @@ +/*-*- 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 2021 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/str/str.h" + +noasan static const char *strlen$pure$x64(const char *p) { + uint64_t w; + for (;;) { + w = *(uint64_t *)p; + if (~w & (w - 0x0101010101010101) & 0x8080808080808080) { + break; + } else { + p += 8; + } + } + return p; +} + +/** + * Returns length of NUL-terminated string. + */ +size_t strlen$pure(const char *s) { + const char *p; + p = s; + while ((uintptr_t)p & 7) { + if (*p) { + ++p; + } else { + return p - s; + } + } + p = strlen$pure$x64(p); + while (*p) ++p; + return p - s; +} diff --git a/libc/str/tprecode16to8.c b/libc/str/tprecode16to8.c index c3a8511e..cfa09e6e 100644 --- a/libc/str/tprecode16to8.c +++ b/libc/str/tprecode16to8.c @@ -27,6 +27,25 @@ static const int16_t kDel16[8] = {127, 127, 127, 127, 127, 127, 127, 127}; +/* 10x speedup for ascii */ +static noasan axdx_t tprecode16to8$sse2(char *dst, size_t dstsize, + const char16_t *src, axdx_t r) { + int16_t v1[8], v2[8], v3[8], vz[8]; + memset(vz, 0, 16); + while (r.ax + 8 < dstsize) { + memcpy(v1, src + r.dx, 16); + pcmpgtw(v2, v1, vz); + pcmpgtw(v3, v1, kDel16); + pandn((void *)v2, (void *)v3, (void *)v2); + if (pmovmskb((void *)v2) != 0xFFFF) break; + packsswb((void *)v1, v1, v1); + memcpy(dst + r.ax, v1, 8); + r.ax += 8; + r.dx += 8; + } + return r; +} + /** * Transcodes UTF-16 to UTF-8. * @@ -40,24 +59,11 @@ axdx_t tprecode16to8(char *dst, size_t dstsize, const char16_t *src) { axdx_t r; uint64_t w; wint_t x, y; - int16_t v1[8], v2[8], v3[8], vz[8]; r.ax = 0; r.dx = 0; for (;;) { if (!IsTiny() && !((uintptr_t)(src + r.dx) & 15)) { - /* 10x speedup for ascii */ - memset(vz, 0, 16); - while (r.ax + 8 < dstsize) { - memcpy(v1, src + r.dx, 16); - pcmpgtw(v2, v1, vz); - pcmpgtw(v3, v1, kDel16); - pandn((void *)v2, (void *)v3, (void *)v2); - if (pmovmskb((void *)v2) != 0xFFFF) break; - packsswb((void *)v1, v1, v1); - memcpy(dst + r.ax, v1, 8); - r.ax += 8; - r.dx += 8; - } + r = tprecode16to8$sse2(dst, dstsize, src, r); } if (!(x = src[r.dx++])) break; if (IsUtf16Cont(x)) continue; diff --git a/libc/str/tprecode8to16.c b/libc/str/tprecode8to16.c index feedc3d0..ba475a8e 100644 --- a/libc/str/tprecode8to16.c +++ b/libc/str/tprecode8to16.c @@ -24,6 +24,25 @@ #include "libc/str/thompike.h" #include "libc/str/utf16.h" +/* 34x speedup for ascii */ +static noasan axdx_t tprecode8to16$sse2(char16_t *dst, size_t dstsize, + const char *src, axdx_t r) { + uint8_t v1[16], v2[16], vz[16]; + memset(vz, 0, 16); + while (r.ax + 16 < dstsize) { + memcpy(v1, src + r.dx, 16); + pcmpgtb((int8_t *)v2, (int8_t *)v1, (int8_t *)vz); + if (pmovmskb(v2) != 0xFFFF) break; + punpcklbw(v2, v1, vz); + punpckhbw(v1, v1, vz); + memcpy(dst + r.ax + 0, v2, 16); + memcpy(dst + r.ax + 8, v1, 16); + r.ax += 16; + r.dx += 16; + } + return r; +} + /** * Transcodes UTF-8 to UTF-16. * @@ -38,24 +57,11 @@ axdx_t tprecode8to16(char16_t *dst, size_t dstsize, const char *src) { unsigned n; uint64_t w; wint_t x, y; - uint8_t v1[16], v2[16], vz[16]; r.ax = 0; r.dx = 0; for (;;) { if (!IsTiny() && !((uintptr_t)(src + r.dx) & 15)) { - /* 34x speedup for ascii */ - memset(vz, 0, 16); - while (r.ax + 16 < dstsize) { - memcpy(v1, src + r.dx, 16); - pcmpgtb((int8_t *)v2, (int8_t *)v1, (int8_t *)vz); - if (pmovmskb(v2) != 0xFFFF) break; - punpcklbw(v2, v1, vz); - punpckhbw(v1, v1, vz); - memcpy(dst + r.ax + 0, v2, 16); - memcpy(dst + r.ax + 8, v1, 16); - r.ax += 16; - r.dx += 16; - } + tprecode8to16$sse2(dst, dstsize, src, r); } x = src[r.dx++] & 0xff; if (ThomPikeCont(x)) continue; diff --git a/libc/str/undeflate.c b/libc/str/undeflate.c index 58246a58..9c752315 100644 --- a/libc/str/undeflate.c +++ b/libc/str/undeflate.c @@ -69,8 +69,8 @@ static const struct DeflateConsts { {{144, 8}, {112, 9}, {24, 7}, {8, 8}, {32, 5}, {0, 0}}, }; -static uint32_t undeflatetree(struct DeflateState *ds, uint32_t *tree, - const uint8_t *lens, size_t symcount) { +static noasan uint32_t undeflatetree(struct DeflateState *ds, uint32_t *tree, + const uint8_t *lens, size_t symcount) { size_t i, len; uint32_t code, slot; uint16_t codes[16], first[16], counts[16]; @@ -96,10 +96,10 @@ static uint32_t undeflatetree(struct DeflateState *ds, uint32_t *tree, return first[15]; } -static struct DeflateHold undeflatesymbol(struct DeflateHold hold, - const uint32_t *tree, - size_t treecount, - uint32_t *out_symbol) { +static noasan struct DeflateHold undeflatesymbol(struct DeflateHold hold, + const uint32_t *tree, + size_t treecount, + uint32_t *out_symbol) { size_t left, right, m; uint32_t search, key; left = 0; @@ -122,17 +122,20 @@ static struct DeflateHold undeflatesymbol(struct DeflateHold hold, return hold; } +/* TODO(jart): Do we really need noasan? */ + /** * Decompresses raw DEFLATE data. * * This is 10x smaller and 10x slower than chromium zlib. * * @param output should be followed by a single guard page, and have - * 36kb of guard pages preceding it too + * 36kb of guard pages preceding it too because buffer overflows + * are part of the design of this algorithm * @note h/t Phil Katz, David Huffman, Claude Shannon */ -ssize_t undeflate(void *output, size_t outputsize, void *input, - size_t inputsize, struct DeflateState *ds) { +noasan ssize_t undeflate(void *output, size_t outputsize, void *input, + size_t inputsize, struct DeflateState *ds) { struct DeflateHold hold; bool isfinalblock; size_t i, nlit, ndist; diff --git a/libc/stubs/asan.S b/libc/stubs/asan.S index 88194dfc..e3a750ce 100644 --- a/libc/stubs/asan.S +++ b/libc/stubs/asan.S @@ -77,10 +77,6 @@ __asan_load32: ud2 .endfn __asan_load32,weak -__asan_noreentry: - ud2 - .endfn __asan_noreentry,weak - __asan_option_detect_stack_use_after_return: ud2 .endfn __asan_option_detect_stack_use_after_return,weak diff --git a/libc/sysv/consts.sh b/libc/sysv/consts.sh index 1dd6339e..d7544d1f 100755 --- a/libc/sysv/consts.sh +++ b/libc/sysv/consts.sh @@ -437,28 +437,28 @@ syscon utime UTIME_OMIT 0x3ffffffe 0x3ffffffe -2 -1 0x3ffffffe # polyf # getauxval() keys # # group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD XENIX Commentary -syscon auxv AT_EXECFD 2 0 2 0 0 -syscon auxv AT_PHDR 3 0 3 0 0 +syscon auxv AT_EXECFD 2 0 2 0 0 # file descriptor of program +syscon auxv AT_PHDR 3 0 3 0 0 # address of program headers of executable syscon auxv AT_PHENT 4 0 4 0 0 syscon auxv AT_PHNUM 5 0 5 0 0 syscon auxv AT_PAGESZ 6 0 6 0 0 -syscon auxv AT_BASE 7 0 7 0 0 -syscon auxv AT_ENTRY 9 0 9 0 0 +syscon auxv AT_BASE 7 0 7 0 0 # address of program interpreter +syscon auxv AT_ENTRY 9 0 9 0 0 # entry address of executable syscon auxv AT_NOTELF 10 0 10 0 0 syscon auxv AT_OSRELDATE 0 0 18 0 0 syscon auxv AT_UID 11 0 0 0 0 syscon auxv AT_EUID 12 0 0 0 0 syscon auxv AT_GID 13 0 0 0 0 syscon auxv AT_EGID 14 0 0 0 0 -syscon auxv AT_PLATFORM 15 0 0 0 0 # RHEL5.0 limit +syscon auxv AT_PLATFORM 15 0 0 0 0 # address of string with hardware platform for rpath interpretation [RHEL5.0 LIMIT] syscon auxv AT_CLKTCK 17 0 0 0 0 syscon auxv AT_DCACHEBSIZE 19 0 0 0 0 syscon auxv AT_ICACHEBSIZE 20 0 0 0 0 syscon auxv AT_UCACHEBSIZE 21 0 0 0 0 syscon auxv AT_SECURE 23 0 0 0 0 syscon auxv AT_BASE_PLATFORM 24 0 0 0 0 -syscon auxv AT_RANDOM 25 0 0 0 0 -syscon auxv AT_EXECFN 31 999 999 999 999 # faked on non-linux +syscon auxv AT_RANDOM 25 0 0 0 0 # address of sixteen bytes of random data +syscon auxv AT_EXECFN 31 999 999 999 999 # address of string containing first argument passed to execve() used when running program [faked on non-linux] syscon auxv AT_SYSINFO_EHDR 33 0 0 0 0 syscon auxv AT_NO_AUTOMOUNT 0x0800 0 0 0 0 diff --git a/libc/sysv/systemfive.S b/libc/sysv/systemfive.S index b980fb59..16ee0077 100644 --- a/libc/sysv/systemfive.S +++ b/libc/sysv/systemfive.S @@ -17,6 +17,9 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/dce.h" +#include "libc/sysv/consts/prot.h" +#include "libc/sysv/consts/nr.h" +#include "libc/sysv/consts/map.h" #include "libc/macros.h" .source __FILE__ @@ -161,9 +164,10 @@ systemfive.xnu: / Initializes System Five system call support. / -/ (1) Extracts parameters passed by kernel, -/ (2) Detects O/S without issuing system calls, -/ (3) Unpacks numbers. +/ (1) Extracts parameters passed by kernel +/ (2) Detects OS without issuing system calls +/ (3) Unpacks magnums from libc/sysv/consts.sh +/ (4) Replaces stack with one we control / / @param %r15 is auxv / @note OpenBSD devs: let us know if you start using auxv @@ -219,26 +223,17 @@ systemfive.init.os: pop %rax add %rcx,%rax stosq #→ __systemfive +/ 𝑠𝑙𝑖𝑑𝑒 +systemfive.init.magnums: push %rdi ezlea syscon.start,di ezlea syscon.end,bx - call systemfive.sleb128unpacker - pop %rdi -/ 𝑠𝑙𝑖𝑑𝑒 -systemfive.init.done: - pop %rsi - pop %rbx - .init.end 300,_init_systemfive,globl,hidden - - .text.startup -systemfive.sleb128unpacker: - .leafprologue or $-1,%r9 2: cmp %rbx,%rdi jnb 5f xor %ecx,%ecx xor %edx,%edx -3: lodsb +3: lodsb # decodes sleb128 mov %rax,%r8 and $127,%r8d sal %cl,%r8 @@ -252,14 +247,66 @@ systemfive.sleb128unpacker: sal %cl,%rax or %rax,%rdx 4: mov %rdx,%rax - cmpq $0,(%rdi) # don't change consts already set - cmovne (%rdi),%rax # @see WinMain() for example + cmpq $0,(%rdi) # dont change if set + cmovne (%rdi),%rax # @see WinMain() stosq jmp 2b -5: .leafepilogue - .previous +5: pop %rdi + pop %rsi + pop %rbx +/ 𝑠𝑙𝑖𝑑𝑒 +#ifndef TINY +systemfive.init.stack: + testb IsWindows() # already did this + jnz systemfive.init.done + testb IsOpenbsd() # todo fix openbsd + jnz systemfive.init.done + push %rdi + push %rsi + mov __NR_mmap,%eax + mov $0x700000000000-STACKSIZE,%rdi + mov $STACKSIZE,%esi + mov $PROT_READ|PROT_WRITE,%edx + mov $MAP_PRIVATE|MAP_FIXED,%r10d + or MAP_ANONYMOUS,%r10d + or MAP_GROWSDOWN,%r10d + or $-1,%r8 + xor %r9d,%r9d + push %r9 # openbsd:pad +/ clc + syscall + pop %r9 + jnc 2f +1: mov %eax,%edi + mov __NR_exit_group,%eax + syscall +2: test %rax,%rax + js 1b + .weak _mmi + ezlea _mmi,cx + test %rcx,%rcx + jz 3f + movb $1,(%rcx) # _mmi.i + movl $(0x700000000000-STACKSIZE)>>16,8(%rcx) # _mmi.p[0].x + movl $(0x700000000000-1)>>16,12(%rcx) # _mmi.p[0].y + mov %edx,20(%rcx) # _mmi.p[0].prot + mov %r10d,24(%rcx) # _mmi.p[0].flags +3: pop %rsi + pop %rdi + leave + pop %rcx + lea STACKSIZE(%rax),%rsp + push %rcx + xor %ebp,%ebp + push %rbp + mov %rsp,%rbp +/ 𝑠𝑙𝑖𝑑𝑒 +#endif /* TINY */ +systemfive.init.done: + nop + .init.end 300,_init_systemfive,globl,hidden -/ Sections for varint encoded numbers. +/ Sections for varint encoded magic numbers. / / These sections are all ordered by (group_name, constant_name). / They're populated by modules simply referencing the symbols. diff --git a/libc/testlib/fixturerunner.c b/libc/testlib/fixturerunner.c index 603dbc16..5ae930fa 100644 --- a/libc/testlib/fixturerunner.c +++ b/libc/testlib/fixturerunner.c @@ -37,8 +37,8 @@ testonly void testlib_runfixtures(testfn_t *test_start, testfn_t *test_end, unsigned i, count; count = testlib_countfixtures(fixture_start, fixture_end); for (i = 0; i < count && !g_testlib_failed; ++i) { - snprintf(g_fixturename, sizeof(g_fixturename), "%s_%s", - fixture_start[i].group, fixture_start[i].name); + (snprintf)(g_fixturename, sizeof(g_fixturename), "%s_%s", + fixture_start[i].group, fixture_start[i].name); _piro(PROT_READ | PROT_WRITE); fixture_start[i].fn(); _piro(PROT_READ); diff --git a/libc/testlib/testlib.h b/libc/testlib/testlib.h index 6ca22fbd..b14dabdb 100644 --- a/libc/testlib/testlib.h +++ b/libc/testlib/testlib.h @@ -233,71 +233,6 @@ COSMOPOLITAN_C_START_ #define EXPECT_LGBL_LT(VAL, GOT) \ expectLongDoubleLessThan(VAL, GOT, #VAL " < " #GOT, false) -/*───────────────────────────────────────────────────────────────────────────│─╗ -│ cosmopolitan § testing library » hardware-accelerated memory safety ─╬─│┼ -╚────────────────────────────────────────────────────────────────────────────│*/ - -typedef void (*testfn_t)(void); - -struct TestFixture { - const char *group; - const char *name; - testfn_t fn; -}; - -struct TestAllocation { - void *mapaddr; - size_t mapsize; - void *useraddr; - size_t usersize; -}; - -struct TestMemoryStack { - size_t i; - size_t n; - struct TestAllocation *p; -}; - -extern struct TestMemoryStack g_testmem; - -void tfree(void *) paramsnonnull(); -void *tmalloc(size_t) returnsnonnull returnspointerwithnoaliases nodiscard - attributeallocsize((1)) returnsaligned((1)); -void *tmemalign(size_t, - size_t) returnsnonnull returnspointerwithnoaliases nodiscard - attributeallocsize((2)) libcesque attributeallocalign((1)); -char *tstrdup(const char *) returnsnonnull returnspointerwithnoaliases nodiscard - returnsaligned((1)); -void *tunbing(const char16_t *) - paramsnonnull() returnsnonnull returnspointerwithnoaliases nodiscard - returnsaligned((1)); -void *tunbinga(size_t, const char16_t *) - paramsnonnull() returnsnonnull returnspointerwithnoaliases nodiscard - attributeallocalign((1)); -void testlib_clearxmmregisters(void); - -#define tgc(TMEM) \ - ({ \ - void *Res; \ - /* volatile b/c testmem only lifo atm */ \ - asm volatile("" ::: "memory"); \ - Res = defer((tfree), (TMEM)); \ - asm volatile("" ::: "memory"); \ - Res; \ - }) - -#define tfree(P) \ - do { \ - __tfree_check(P); \ - (tfree)(P); \ - } while (0) - -#define __tfree_check(P) \ - ASSERT_BETWEEN(g_testmem.p[g_testmem.i - 1].useraddr, \ - ((char *)g_testmem.p[g_testmem.i - 1].useraddr + \ - g_testmem.p[g_testmem.i - 1].usersize), \ - P) - /*───────────────────────────────────────────────────────────────────────────│─╗ │ cosmopolitan § testing library » implementation details ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ @@ -310,6 +245,14 @@ void testlib_clearxmmregisters(void); const char *file; \ int line +typedef void (*testfn_t)(void); + +struct TestFixture { + const char *group; + const char *name; + testfn_t fn; +}; + extern char g_fixturename[256]; extern bool g_testlib_shoulddebugbreak; /* set by testmain */ extern unsigned g_testlib_ran; /* set by wrappers */ @@ -374,6 +317,7 @@ void testlib_formatbinaryasglyphs(const char16_t *, const void *, size_t, char **, char **); bool testlib_almostequallongdouble(long double, long double); void testlib_incrementfailed(void); +void testlib_clearxmmregisters(void); forceinline void testlib_ontest() { YOINK(__testcase_start); diff --git a/libc/testlib/testlib.mk b/libc/testlib/testlib.mk index 50b54fe2..dacb0f6e 100644 --- a/libc/testlib/testlib.mk +++ b/libc/testlib/testlib.mk @@ -56,7 +56,6 @@ LIBC_TESTLIB_A_SRCS_C = \ libc/testlib/shoulddebugbreak.c \ libc/testlib/showerror.c \ libc/testlib/showerror_.c \ - libc/testlib/testmem.c \ libc/testlib/strequals.c \ libc/testlib/startswith.c \ libc/testlib/endswith.c \ diff --git a/libc/testlib/testmem.c b/libc/testlib/testmem.c deleted file mode 100644 index 2d49473b..00000000 --- a/libc/testlib/testmem.c +++ /dev/null @@ -1,179 +0,0 @@ -/*-*- 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 2020 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/assert.h" -#include "libc/bits/safemacros.h" -#include "libc/calls/calls.h" -#include "libc/dce.h" -#include "libc/fmt/bing.internal.h" -#include "libc/limits.h" -#include "libc/log/check.h" -#include "libc/log/log.h" -#include "libc/macros.h" -#include "libc/mem/mem.h" -#include "libc/runtime/sysconf.h" -#include "libc/str/str.h" -#include "libc/sysv/consts/map.h" -#include "libc/sysv/consts/prot.h" -#include "libc/testlib/testlib.h" - -/* TODO(jart): DELETE */ - -struct TestMemoryStack g_testmem; -struct TestMemoryStack g_testmem_trash; -static struct TestAllocation g_testmem_scratch[2][8]; -static const char kMemZero[1]; -static bool g_atstartofpage; - -static struct TestAllocation testmem_push(struct TestMemoryStack *stack, - struct TestAllocation entry) { - if (stack->i == stack->n) { - if (!__grow(&stack->p, &stack->n, sizeof(struct TestAllocation), 0)) { - abort(); - } - } - return (stack->p[stack->i++] = entry); -} - -static struct TestAllocation testmem_pop(struct TestMemoryStack *stack) { - assert(stack->i > 0); - struct TestAllocation res = stack->p[--stack->i]; - return res; -} - -static void testmem_destroy(struct TestAllocation alloc) { - if (munmap(alloc.mapaddr, alloc.mapsize) == -1) perror("munmap"), __die(); -} - -static struct TestAllocation talloc(size_t n) { - struct TestAllocation alloc; - if (n) { - while (g_testmem_trash.i) { - struct TestAllocation trash = testmem_pop(&g_testmem_trash); - if (n <= trash.usersize) { - return trash; - } else { - testmem_destroy(trash); - } - } - alloc.mapsize = ROUNDUP(n + PAGESIZE * 2, FRAMESIZE); - CHECK_NE(MAP_FAILED, (alloc.mapaddr = mapanon(alloc.mapsize))); - CHECK_NE(-1, mprotect(alloc.mapaddr, PAGESIZE, PROT_NONE)); - CHECK_NE(-1, mprotect((char *)alloc.mapaddr + alloc.mapsize - PAGESIZE, - PAGESIZE, PROT_NONE)); - alloc.useraddr = (char *)alloc.mapaddr + PAGESIZE; - alloc.usersize = alloc.mapsize - PAGESIZE * 2; - CHECK_GE(alloc.usersize, n); - return alloc; - } else { - alloc.mapaddr = (/*unconst*/ void *)kMemZero; - alloc.mapsize = 0; - alloc.useraddr = (/*unconst*/ void *)kMemZero; - alloc.usersize = 0; - return alloc; - } -} - -static textstartup void testmem_init(void) { - g_testmem.p = g_testmem_scratch[0]; - g_testmem.n = ARRAYLEN(g_testmem_scratch[0]); - g_testmem_trash.p = g_testmem_scratch[1]; - g_testmem_trash.n = ARRAYLEN(g_testmem_scratch[1]); -} - -const void *const testmem_ctor[] initarray = {testmem_init}; - -FIXTURE(testmemory, triggerOffByOneArrayErrors) { - /* automate testing buffer overflows *and* underflows */ - g_atstartofpage = true; -} - -/** - * Allocates memory with properties useful for testing. - * - * This returns a pointer 𝑝 where reading or writing to either 𝑝[-1] or - * 𝑝[𝑛+𝟷] will immediately trigger a segmentation fault; and bytes are - * initialized to 10100101 (A5). - * - * Implementation Details: Accomplishing this entails two things. First, - * we grant each allocation a page granular memory mapping, with access - * to the two adjacent pages disabled. Second, since hardware memory - * protection isn't 1-byte granular, we add a fixture so each test runs - * a second time; the first call we return a pointer where the data is - * placed on the righthand side, and the second call we return the data - * on the lefthand side, thereby allowing both underflow/overflow - * off-by-one out-of-bounds accesses to be detected. - */ -void *tmalloc(size_t n) { - struct TestAllocation alloc = talloc(n); - memset(alloc.useraddr, 0xa5, alloc.usersize); - testmem_push(&g_testmem, alloc); - return (char *)alloc.useraddr + (g_atstartofpage ? 0 : alloc.usersize - n); -} - -/** - * Same as tmalloc() but guarantees a specific alignment. - * - * Reading or writing to either 𝑝[-1] or 𝑝[roundup(𝑛+𝟷,𝑎)] will - * immediately trigger a segmentation fault. - * - * @param 𝑎 is alignment in bytes, e.g. 16 - * @param 𝑛 is number of bytes - */ -void *tmemalign(size_t a, size_t n) { - /* TODO(jart): ASAN detect 𝑝[𝑛+𝟷] */ - return tmalloc(ROUNDUP(n, a)); -} - -/** - * Same as tunbing() w/ alignment guarantee. - */ -void *tunbinga(size_t a, const char16_t *binglyphs) { - size_t size; - EXPECT_NE(0, (size = strlen16(binglyphs))); - return unbingbuf(tmemalign(a, size), size, binglyphs, -1); -} - -/** - * Decodes CP437 glyphs to bounds-checked binary buffer, e.g. - * - * char *mem = tunbing(u" ☺☻♥♦"); - * EXPECT_EQ(0, memcmp("\0\1\2\3\4", mem, 5)); - * tfree(mem); - * - * @see tunbing(), unbingstr(), unbing() - */ -void *tunbing(const char16_t *binglyphs) { - return tunbinga(1, binglyphs); -} - -/** - * Frees memory allocated with tmalloc(). - * This needs to be called in LIFO order. - * @param - */ -void(tfree)(void *p) { - struct TestAllocation alloc; - __tfree_check(p); - alloc = testmem_pop(&g_testmem); - if (alloc.mapsize) testmem_push(&g_testmem_trash, alloc); -} - -char *tstrdup(const char *s) { - return strcpy(tmalloc(strlen(s) + 1), s); -} diff --git a/libc/x/tunbing.c b/libc/x/tunbing.c new file mode 100644 index 00000000..def9ae49 --- /dev/null +++ b/libc/x/tunbing.c @@ -0,0 +1,43 @@ +/*-*- 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 2021 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/bing.internal.h" +#include "libc/str/str.h" +#include "libc/x/x.h" + +/** + * Same as xunbing() w/ alignment guarantee. + */ +void *xunbinga(size_t a, const char16_t *binglyphs) { + size_t size; + size = strlen16(binglyphs); + return unbingbuf(xmemalign(a, size), size, binglyphs, -1); +} + +/** + * Decodes CP437 glyphs to bounds-checked binary buffer, e.g. + * + * char *mem = xunbing(u" ☺☻♥♦"); + * EXPECT_EQ(0, memcmp("\0\1\2\3\4", mem, 5)); + * tfree(mem); + * + * @see xunbing(), unbingstr(), unbing() + */ +void *xunbing(const char16_t *binglyphs) { + return xunbinga(1, binglyphs); +} diff --git a/libc/x/x.h b/libc/x/x.h index 289a0536..ce3339e4 100644 --- a/libc/x/x.h +++ b/libc/x/x.h @@ -46,6 +46,8 @@ char *xstrndup(const char *, size_t) _XPNN _XMAL; char *xstrcat(const char *, ...) paramsnonnull((1)) nullterminated() _XMAL; char *xstrmul(const char *, size_t) paramsnonnull((1)) _XMAL; char *xinet_ntop(int, const void *) _XPNN _XMAL; +void *xunbinga(size_t, const char16_t *) attributeallocalign((1)) _XMAL _XRET; +void *xunbing(const char16_t *) _XMAL _XRET; /*───────────────────────────────────────────────────────────────────────────│─╗ │ cosmopolitan § eXtended apis » files ─╬─│┼ diff --git a/libc/x/xslurp.c b/libc/x/xslurp.c index 4c2e9293..bbaa536c 100644 --- a/libc/x/xslurp.c +++ b/libc/x/xslurp.c @@ -38,7 +38,7 @@ char *xslurp(const char *path, size_t *opt_out_size) { struct stat st; res = NULL; if ((fd = open(path, O_RDONLY)) != -1) { - if (fstat(fd, &st) != -1 && (res = valloc(st.st_size))) { + if (fstat(fd, &st) != -1 && (res = valloc(st.st_size + 1))) { if (st.st_size > 2 * 1024 * 1024) { fadvise(fd, 0, st.st_size, MADV_SEQUENTIAL); } diff --git a/net/http/http.mk b/net/http/http.mk index c9b1260a..163f0b8e 100644 --- a/net/http/http.mk +++ b/net/http/http.mk @@ -31,7 +31,6 @@ NET_HTTP_A_DIRECTDEPS = \ LIBC_FMT \ LIBC_INTRIN \ LIBC_LOG \ - LIBC_LOG_ASAN \ LIBC_NEXGEN32E \ LIBC_RUNTIME \ LIBC_SOCK \ diff --git a/test/ape/lib/smapsort_test.c b/test/ape/lib/smapsort_test.c index df96a635..3454a68b 100644 --- a/test/ape/lib/smapsort_test.c +++ b/test/ape/lib/smapsort_test.c @@ -17,16 +17,17 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "ape/lib/pc.h" +#include "libc/mem/mem.h" #include "libc/str/str.h" #include "libc/testlib/testlib.h" TEST(smapsort, testEmpty_doesntOverrunBuffer) { - struct SmapEntry *smap = tmalloc(sizeof(struct SmapEntry)); + struct SmapEntry *smap = malloc(sizeof(struct SmapEntry)); memset(smap, 0, sizeof(struct SmapEntry)); smapsort(smap); EXPECT_EQ(0, smap[0].addr); EXPECT_EQ(0, smap[0].size); - tfree(smap); + free(smap); } /* TEST(smapsort, testSorted_doesNothing) { */ diff --git a/test/ape/lib/test.mk b/test/ape/lib/test.mk index 172126f7..e340fa8f 100644 --- a/test/ape/lib/test.mk +++ b/test/ape/lib/test.mk @@ -26,6 +26,7 @@ TEST_APE_LIB_DIRECTDEPS = \ APE_LIB \ LIBC_INTRIN \ LIBC_LOG \ + LIBC_MEM \ LIBC_NEXGEN32E \ LIBC_RUNTIME \ LIBC_STR \ diff --git a/test/dsp/core/test.mk b/test/dsp/core/test.mk index 91b722b6..afa8171c 100644 --- a/test/dsp/core/test.mk +++ b/test/dsp/core/test.mk @@ -46,10 +46,6 @@ o/$(MODE)/test/dsp/core/%.com.dbg: \ $(APE) @$(APELINK) -# $(TEST_DSP_CORE_OBJS): \ -# OVERRIDE_CFLAGS += \ -# -fsanitize=address - .PHONY: o/$(MODE)/test/dsp/core o/$(MODE)/test/dsp/core: \ $(TEST_DSP_CORE_BINS) \ diff --git a/test/dsp/scale/magikarp_test.c b/test/dsp/scale/magikarp_test.c index 5d201b79..ed8ec94f 100644 --- a/test/dsp/scale/magikarp_test.c +++ b/test/dsp/scale/magikarp_test.c @@ -25,6 +25,7 @@ #include "libc/math.h" #include "libc/mem/mem.h" #include "libc/nexgen32e/x86feature.h" +#include "libc/runtime/gc.h" #include "libc/str/str.h" #include "libc/testlib/ezbench.h" #include "libc/testlib/testlib.h" @@ -40,9 +41,9 @@ TEST(magikarp, testConvolve) { u"λλ  λλ  λλ  λλ  " u"λλ  λλ  λλ  λλ  ", cDecimate2xUint8x8(32 * 3, - tgc(tunbing(u"λλλλ    λλλλ    λλλλ    λλλλ    " - u"λλλλ    λλλλ    λλλλ    λλλλ    " - u"λλλλ    λλλλ    λλλλ    λλλλ    ")), + gc(xunbing(u"λλλλ    λλλλ    λλλλ    λλλλ    " + u"λλλλ    λλλλ    λλλλ    λλλλ    " + u"λλλλ    λλλλ    λλλλ    λλλλ    ")), K)); } @@ -53,9 +54,9 @@ TEST(magikarp, testConvolveMin1) { u"λλ  λλ  λλ  λλ  " u"λλ  λλ  λλ  λλ  ", cDecimate2xUint8x8(32 * 3 - 1, - tgc(tunbing(u"λλλλ    λλλλ    λλλλ    λλλλ    " - u"λλλλ    λλλλ    λλλλ    λλλλ    " - u"λλλλ    λλλλ    λλλλ    λλλλ   ")), + gc(xunbing(u"λλλλ    λλλλ    λλλλ    λλλλ    " + u"λλλλ    λλλλ    λλλλ    λλλλ    " + u"λλλλ    λλλλ    λλλλ    λλλλ   ")), K)); } @@ -71,14 +72,14 @@ TEST(magikarp, testConvolve2) { u"┴├┼╟╔╦═╧╤╙╒╫┘█▌▀" u"ßπστΘδφ∩±≤⌡≈∙√²λ", cDecimate2xUint8x8(256, - tgc(tunbing(u" ☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼" - u" !“#$%&‘()*+,-./0123456789:;<=>⁇" - u"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" - u"`abcdefghijklmnopqrstuvwxyz{|}~⌂" - u"ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥€ƒ" - u"áíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐" - u"└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀" - u"αßΓπΣσμτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■λ")), + gc(xunbing(u" ☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼" + u" !“#$%&‘()*+,-./0123456789:;<=>⁇" + u"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" + u"`abcdefghijklmnopqrstuvwxyz{|}~⌂" + u"ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥€ƒ" + u"áíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐" + u"└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀" + u"αßΓπΣσμτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙×√ⁿ²■λ")), K)); } @@ -147,8 +148,8 @@ noopopppqqqqqqqqqqqqqqqppoooonn", BENCH(magikarp, bench) { /* 30ms */ unsigned char kMagkern[16] = {4, 12, 12, 4}; signed char kMagikarp[16] = {-1, -3, 3, 17, 17, 3, -3, -1}; - unsigned char(*Me)[HDY][HDX] = tgc(tmalloc((HDX + 1) * (HDY + 1))); - unsigned char(*Mo)[HDY][HDX] = tgc(tmalloc((HDX + 1) * (HDY + 1))); + unsigned char(*Me)[HDY][HDX] = gc(malloc((HDX + 1) * (HDY + 1))); + unsigned char(*Mo)[HDY][HDX] = gc(malloc((HDX + 1) * (HDY + 1))); if (X86_HAVE(AVX)) { EZBENCH2("Decimate2xUint8x8", donothing, cDecimate2xUint8x8((HDX * HDY - 16 - 8) / 2 / 8 * 8, (void *)Me, diff --git a/test/dsp/tty/windex_test.c b/test/dsp/tty/windex_test.c index 6114558a..aedd130c 100644 --- a/test/dsp/tty/windex_test.c +++ b/test/dsp/tty/windex_test.c @@ -21,7 +21,9 @@ #include "libc/bits/bits.h" #include "libc/limits.h" #include "libc/macros.h" +#include "libc/mem/mem.h" #include "libc/nexgen32e/x86feature.h" +#include "libc/runtime/gc.h" #include "libc/str/str.h" #include "libc/testlib/ezbench.h" #include "libc/testlib/testlib.h" @@ -54,12 +56,12 @@ const short kW3[64] forcealign(32) = { 1730, 2041, 7707, 5096, 6876, 1324, 1242, 7, 0x7fff, }; -#define TestIt(impl, index, value, n, array) \ - ({ \ - short *a = memcpy(tgc(tmemalign(32, n * 2)), array, n * 2); \ - unsigned res = impl(array, n); \ - ASSERT_EQ(index, res); \ - ASSERT_EQ(value, a[res]); \ +#define TestIt(impl, index, value, n, array) \ + ({ \ + short *a = memcpy(gc(memalign(32, n * 2)), array, n * 2); \ + unsigned res = impl(array, n); \ + ASSERT_EQ(index, res); \ + ASSERT_EQ(value, a[res]); \ }) TEST(windex, testRealWorldPicks) { diff --git a/test/libc/alg/comparator_test.c b/test/libc/alg/comparator_test.c index 6090ee2b..468b1b4c 100644 --- a/test/libc/alg/comparator_test.c +++ b/test/libc/alg/comparator_test.c @@ -18,12 +18,13 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/alg/alg.h" #include "libc/bits/bits.h" +#include "libc/mem/mem.h" #include "libc/str/str.h" #include "libc/testlib/testlib.h" TEST(comparator, testByteCompare) { - char *b1 = tmalloc(1); - char *b2 = tmalloc(1); + char *b1 = malloc(1); + char *b2 = malloc(1); /* sign doesn't matter */ EXPECT_EQ(cmpsb(memcpy(b1, "a", 1), memcpy(b2, "a", 1)), 0); EXPECT_LT(cmpsb(memcpy(b1, "a", 1), memcpy(b2, "z", 1)), 0); @@ -41,26 +42,26 @@ TEST(comparator, testByteCompare) { /* two's complement bane */ EXPECT_GT(cmpsb(memcpy(b1, "\x7f", 1), memcpy(b2, "\x80", 1)), 0); EXPECT_LT(cmpub(memcpy(b1, "\x7f", 1), memcpy(b2, "\x80", 1)), 0); - tfree(b2); - tfree(b1); + free(b2); + free(b1); } TEST(comparator, testWordCompare) { - char *b1 = tmalloc(2); - char *b2 = tmalloc(2); + char *b1 = malloc(2); + char *b2 = malloc(2); EXPECT_EQ(cmpsw(memcpy(b1, "\x00\x80", 2), memcpy(b2, "\x00\x80", 2)), 0); EXPECT_GT(cmpsw(memcpy(b1, "\x00\x7f", 2), memcpy(b2, "\x00\x80", 2)), 0); EXPECT_LT(cmpsw(memcpy(b1, "\x00\x80", 2), memcpy(b2, "\x00\x7f", 2)), 0); EXPECT_EQ(cmpuw(memcpy(b1, "\x00\x80", 2), memcpy(b2, "\x00\x80", 2)), 0); EXPECT_LT(cmpuw(memcpy(b1, "\x00\x7f", 2), memcpy(b2, "\x00\x80", 2)), 0); EXPECT_GT(cmpuw(memcpy(b1, "\x00\x80", 2), memcpy(b2, "\x00\x7f", 2)), 0); - tfree(b2); - tfree(b1); + free(b2); + free(b1); } TEST(comparator, testDoublewordCompare) { - char *b1 = tmalloc(4); - char *b2 = tmalloc(4); + char *b1 = malloc(4); + char *b2 = malloc(4); EXPECT_EQ(cmpsl(memcpy(b1, "\x00\x00\x00\x80", 4), memcpy(b2, "\x00\x00\x00\x80", 4)), 0); @@ -79,13 +80,13 @@ TEST(comparator, testDoublewordCompare) { EXPECT_GT(cmpul(memcpy(b1, "\x00\x00\x00\x80", 4), memcpy(b2, "\x00\x00\x00\x7f", 4)), 0); - tfree(b2); - tfree(b1); + free(b2); + free(b1); } TEST(comparator, testQuadwordCompare) { - char *b1 = tmalloc(8); - char *b2 = tmalloc(8); + char *b1 = malloc(8); + char *b2 = malloc(8); EXPECT_EQ(cmpsq(memcpy(b1, "\x00\x00\x00\x00\x00\x00\x00\x80", 8), memcpy(b2, "\x00\x00\x00\x00\x00\x00\x00\x80", 8)), 0); @@ -104,6 +105,6 @@ TEST(comparator, testQuadwordCompare) { EXPECT_GT(cmpuq(memcpy(b1, "\x00\x00\x00\x00\x00\x00\x00\x80", 8), memcpy(b2, "\x00\x00\x00\x00\x00\x00\x00\x7f", 8)), 0); - tfree(b2); - tfree(b1); + free(b2); + free(b1); } diff --git a/test/libc/alg/djbsort_test.c b/test/libc/alg/djbsort_test.c index 45fac768..554e2bf8 100644 --- a/test/libc/alg/djbsort_test.c +++ b/test/libc/alg/djbsort_test.c @@ -38,9 +38,9 @@ int32_t *a, *b, *c; TEST(djbsort, test4) { static const int kA[] = {4, 3, 2, 1}; n = ARRAYLEN(kA); - a = memcpy(tgc(tmalloc(n * 4)), kA, n * 4); - b = memcpy(tgc(tmalloc(n * 4)), kA, n * 4); - c = memcpy(tgc(tmalloc(n * 4)), kA, n * 4); + a = memcpy(gc(malloc(n * 4)), kA, n * 4); + b = memcpy(gc(malloc(n * 4)), kA, n * 4); + c = memcpy(gc(malloc(n * 4)), kA, n * 4); insertionsort(a, n); djbsort$avx2(b, n); djbsort(c, n); @@ -65,9 +65,9 @@ TEST(djbsort, test64) { -1323943608, -1219421355, -582289873, 1062699814, }; n = ARRAYLEN(kA); - a = memcpy(tgc(tmalloc(n * 4)), kA, n * 4); - b = memcpy(tgc(tmalloc(n * 4)), kA, n * 4); - c = memcpy(tgc(tmalloc(n * 4)), kA, n * 4); + a = memcpy(gc(malloc(n * 4)), kA, n * 4); + b = memcpy(gc(malloc(n * 4)), kA, n * 4); + c = memcpy(gc(malloc(n * 4)), kA, n * 4); insertionsort(a, n); djbsort(c, n); ASSERT_EQ(0, memcmp(a, c, n * 4)); diff --git a/test/libc/alg/qsort_test.c b/test/libc/alg/qsort_test.c index 3e4d3c35..b7d6bdfe 100644 --- a/test/libc/alg/qsort_test.c +++ b/test/libc/alg/qsort_test.c @@ -19,6 +19,7 @@ #include "libc/alg/alg.h" #include "libc/bits/bits.h" #include "libc/macros.h" +#include "libc/mem/mem.h" #include "libc/str/str.h" #include "libc/testlib/testlib.h" @@ -29,9 +30,9 @@ TEST(qsort, test) { const int32_t B[][2] = {{-31, 'd'}, {0, 'e'}, {1, 'j'}, {2, 'c'}, {2, 'g'}, {4, 'a'}, {65, 'b'}, {83, 'h'}, {99, 'f'}, {782, 'i'}}; - int32_t(*M)[2] = tmalloc(sizeof(A)); + int32_t(*M)[2] = malloc(sizeof(A)); memcpy(M, B, sizeof(A)); qsort(M, ARRAYLEN(A), sizeof(*M), cmpsl); EXPECT_EQ(0, memcmp(M, B, sizeof(B))); - tfree(M); + free(M); } diff --git a/test/libc/dns/dnsheader_test.c b/test/libc/dns/dnsheader_test.c index 928294fa..0de9a15f 100644 --- a/test/libc/dns/dnsheader_test.c +++ b/test/libc/dns/dnsheader_test.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/dns/dns.h" #include "libc/dns/dnsheader.h" +#include "libc/mem/mem.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" #include "libc/testlib/testlib.h" @@ -28,20 +29,20 @@ TEST(serializednsheader, test) { header.id = 255; header.bf1 = true; header.qdcount = 1; - uint8_t *buf = tmalloc(12); + uint8_t *buf = malloc(12); ASSERT_EQ(12, serializednsheader(buf, 12, header)); EXPECT_BINEQ(u" λ☺  ☺      ", buf); - tfree(buf); + free(buf); } TEST(serializednsheader, fuzzSymmetry) { - uint8_t *buf = tmalloc(12); - struct DnsHeader *in = tmalloc(sizeof(struct DnsHeader)); - struct DnsHeader *out = tmalloc(sizeof(struct DnsHeader)); + uint8_t *buf = malloc(12); + struct DnsHeader *in = malloc(sizeof(struct DnsHeader)); + struct DnsHeader *out = malloc(sizeof(struct DnsHeader)); ASSERT_EQ(12, serializednsheader(buf, 12, *in)); ASSERT_EQ(12, deserializednsheader(out, buf, 12)); ASSERT_EQ(0, memcmp(in, out, 12)); - tfree(out); - tfree(in); - tfree(buf); + free(out); + free(in); + free(buf); } diff --git a/test/libc/dns/dnsnamecmp_test.c b/test/libc/dns/dnsnamecmp_test.c index 0852f45a..55ba2b48 100644 --- a/test/libc/dns/dnsnamecmp_test.c +++ b/test/libc/dns/dnsnamecmp_test.c @@ -17,21 +17,22 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/dns/dns.h" +#include "libc/mem/mem.h" #include "libc/str/str.h" #include "libc/testlib/testlib.h" TEST(dnsnamecmp, testEmpty) { - char *A = strcpy(tmalloc(1), ""); - char *B = strcpy(tmalloc(1), ""); + char *A = strcpy(malloc(1), ""); + char *B = strcpy(malloc(1), ""); EXPECT_EQ(dnsnamecmp(A, B), 0); EXPECT_EQ(dnsnamecmp(A, A), 0); - tfree(B); - tfree(A); + free(B); + free(A); } TEST(dnsnamecmp, testDotless_caseInsensitiveBehavior) { - char *A = tmalloc(2); - char *B = tmalloc(2); + char *A = malloc(2); + char *B = malloc(2); EXPECT_EQ(dnsnamecmp(strcpy(A, "a"), strcpy(B, "a")), 0); EXPECT_EQ(dnsnamecmp(A, A), 0); EXPECT_EQ(dnsnamecmp(strcpy(A, "a"), strcpy(B, "A")), 0); @@ -39,13 +40,13 @@ TEST(dnsnamecmp, testDotless_caseInsensitiveBehavior) { EXPECT_LT(dnsnamecmp(strcpy(A, "a"), strcpy(B, "b")), 0); EXPECT_LT(dnsnamecmp(strcpy(A, "a"), strcpy(B, "B")), 0); EXPECT_GT(dnsnamecmp(strcpy(A, "d"), strcpy(B, "a")), 0); - tfree(B); - tfree(A); + free(B); + free(A); } TEST(dnsnamecmp, testMultiLabel_lexiReverse) { - char *A = tmalloc(16); - char *B = tmalloc(16); + char *A = malloc(16); + char *B = malloc(16); EXPECT_EQ(dnsnamecmp(strcpy(A, "a.example"), strcpy(B, "a.example")), 0); EXPECT_GT(dnsnamecmp(strcpy(A, "b.example"), strcpy(B, "a.example")), 0); EXPECT_LT(dnsnamecmp(strcpy(A, "b.example"), strcpy(B, "a.examplz")), 0); @@ -53,48 +54,48 @@ TEST(dnsnamecmp, testMultiLabel_lexiReverse) { EXPECT_EQ(dnsnamecmp(strcpy(A, "c.a.example"), strcpy(B, "c.a.example")), 0); EXPECT_GT(dnsnamecmp(strcpy(A, "d.a.example"), strcpy(B, "c.a.example")), 0); EXPECT_LT(dnsnamecmp(strcpy(A, "cat.example"), strcpy(B, "lol.example")), 0); - tfree(B); - tfree(A); + free(B); + free(A); } TEST(dnsnamecmp, testTldDotQualifier_canBeEqualToDottedNames) { - char *A = tmalloc(16); - char *B = tmalloc(16); + char *A = malloc(16); + char *B = malloc(16); EXPECT_EQ(dnsnamecmp(strcpy(B, "aaa.example."), strcpy(A, "aaa.example")), 0); - tfree(B); - tfree(A); + free(B); + free(A); } TEST(dnsnamecmp, testFullyQualified_alwaysComesFirst) { - char *A = tmalloc(16); - char *B = tmalloc(16); + char *A = malloc(16); + char *B = malloc(16); EXPECT_LT(dnsnamecmp(strcpy(B, "aaa.example."), strcpy(A, "zzz")), 0); EXPECT_LT(dnsnamecmp(strcpy(B, "zzz.example."), strcpy(A, "aaa")), 0); EXPECT_GT(dnsnamecmp(strcpy(A, "zzz"), strcpy(B, "aaa.example.")), 0); EXPECT_GT(dnsnamecmp(strcpy(A, "aaa"), strcpy(B, "zzz.example.")), 0); - tfree(B); - tfree(A); + free(B); + free(A); } TEST(dnsnamecmp, testLikelySld_alwaysComesBeforeLocalName) { - char *A = tmalloc(16); - char *B = tmalloc(16); + char *A = malloc(16); + char *B = malloc(16); EXPECT_LT(dnsnamecmp(strcpy(B, "z.e"), strcpy(A, "a")), 0); EXPECT_LT(dnsnamecmp(strcpy(B, "aaa.example"), strcpy(A, "zzz")), 0); EXPECT_LT(dnsnamecmp(strcpy(B, "zzz.example"), strcpy(A, "aaa")), 0); EXPECT_GT(dnsnamecmp(strcpy(A, "zzz"), strcpy(B, "aaa.example")), 0); EXPECT_GT(dnsnamecmp(strcpy(A, "aaa"), strcpy(B, "zzz.example")), 0); - tfree(B); - tfree(A); + free(B); + free(A); } TEST(dnsnamecmp, testLikelySubdomain_alwaysComesAfterSld) { - char *A = tmalloc(16); - char *B = tmalloc(16); + char *A = malloc(16); + char *B = malloc(16); EXPECT_LT(dnsnamecmp(strcpy(B, "a.e"), strcpy(A, "z.a.e")), 0); EXPECT_GT(dnsnamecmp(strcpy(A, "z.a.e"), strcpy(B, "a.e")), 0); EXPECT_LT(dnsnamecmp(strcpy(B, "b.e"), strcpy(A, "a.b.e")), 0); EXPECT_GT(dnsnamecmp(strcpy(A, "a.b.e"), strcpy(B, "b.e")), 0); - tfree(B); - tfree(A); + free(B); + free(A); } diff --git a/test/libc/dns/dnsquestion_test.c b/test/libc/dns/dnsquestion_test.c index d26dbfe7..0fb1078d 100644 --- a/test/libc/dns/dnsquestion_test.c +++ b/test/libc/dns/dnsquestion_test.c @@ -19,11 +19,12 @@ #include "libc/dns/dns.h" #include "libc/dns/dnsquestion.h" #include "libc/errno.h" +#include "libc/mem/mem.h" #include "libc/testlib/testlib.h" TEST(serializednsquestion, test) { - uint8_t *buf = tmalloc(1 + 3 + 1 + 3 + 1 + 4); - char *name = tstrdup("foo.bar"); + uint8_t *buf = malloc(1 + 3 + 1 + 3 + 1 + 4); + char *name = strdup("foo.bar"); struct DnsQuestion dq; dq.qname = name; dq.qtype = 0x0201; @@ -31,19 +32,19 @@ TEST(serializednsquestion, test) { EXPECT_EQ(1 + 3 + 1 + 3 + 1 + 4, serializednsquestion(buf, 1 + 3 + 1 + 3 + 1 + 4, dq)); EXPECT_BINEQ(u"♥foo♥bar ☻☺☺☻", buf); - tfree(name); - tfree(buf); + free(name); + free(buf); } TEST(serializednsquestion, testNoSpace) { - uint8_t *buf = tmalloc(1 + 3 + 1 + 3 + 1 + 3); - char *name = tstrdup("foo.bar"); + uint8_t *buf = malloc(1 + 3 + 1 + 3 + 1 + 3); + char *name = strdup("foo.bar"); struct DnsQuestion dq; dq.qname = name; dq.qtype = 0x0201; dq.qclass = 0x0102; EXPECT_EQ(-1, serializednsquestion(buf, 1 + 3 + 1 + 3 + 1 + 3, dq)); EXPECT_EQ(ENOSPC, errno); - tfree(name); - tfree(buf); + free(name); + free(buf); } diff --git a/test/libc/dns/pascalifydnsname_test.c b/test/libc/dns/pascalifydnsname_test.c index ff166719..2b372ec4 100644 --- a/test/libc/dns/pascalifydnsname_test.c +++ b/test/libc/dns/pascalifydnsname_test.c @@ -18,61 +18,62 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/dns/dns.h" #include "libc/errno.h" +#include "libc/mem/mem.h" #include "libc/str/str.h" #include "libc/testlib/testlib.h" TEST(pascalifydnsname, testEmpty) { - uint8_t *buf = tmalloc(1); - char *name = tstrdup(""); + uint8_t *buf = malloc(1); + char *name = strdup(""); EXPECT_EQ(0, pascalifydnsname(buf, 1, name)); EXPECT_BINEQ(u" ", buf); - tfree(name); - tfree(buf); + free(name); + free(buf); } TEST(pascalifydnsname, testOneLabel) { - uint8_t *buf = tmalloc(1 + 3 + 1); - char *name = tstrdup("foo"); + uint8_t *buf = malloc(1 + 3 + 1); + char *name = strdup("foo"); EXPECT_EQ(1 + 3, pascalifydnsname(buf, 1 + 3 + 1, name)); EXPECT_BINEQ(u"♥foo ", buf); - tfree(name); - tfree(buf); + free(name); + free(buf); } TEST(pascalifydnsname, testTwoLabels) { - uint8_t *buf = tmalloc(1 + 3 + 1 + 3 + 1); - char *name = tstrdup("foo.bar"); + uint8_t *buf = malloc(1 + 3 + 1 + 3 + 1); + char *name = strdup("foo.bar"); EXPECT_EQ(1 + 3 + 1 + 3, pascalifydnsname(buf, 1 + 3 + 1 + 3 + 1, name)); EXPECT_BINEQ(u"♥foo♥bar ", buf); - tfree(name); - tfree(buf); + free(name); + free(buf); } TEST(pascalifydnsname, testFqdnDot_isntIncluded) { - uint8_t *buf = tmalloc(1 + 3 + 1 + 3 + 1); - char *name = tstrdup("foo.bar."); + uint8_t *buf = malloc(1 + 3 + 1 + 3 + 1); + char *name = strdup("foo.bar."); EXPECT_EQ(1 + 3 + 1 + 3, pascalifydnsname(buf, 1 + 3 + 1 + 3 + 1, name)); EXPECT_BINEQ(u"♥foo♥bar ", buf); - tfree(name); - tfree(buf); + free(name); + free(buf); } TEST(pascalifydnsname, testTooLong) { - uint8_t *buf = tmalloc(1); - char *name = tmalloc(1000); + uint8_t *buf = malloc(1); + char *name = malloc(1000); memset(name, '.', 999); name[999] = '\0'; EXPECT_EQ(-1, pascalifydnsname(buf, 1, name)); EXPECT_EQ(ENAMETOOLONG, errno); - tfree(name); - tfree(buf); + free(name); + free(buf); } TEST(pascalifydnsname, testNoSpace) { - uint8_t *buf = tmalloc(1); - char *name = tstrdup("foo"); + uint8_t *buf = malloc(1); + char *name = strdup("foo"); EXPECT_EQ(-1, pascalifydnsname(buf, 1, name)); EXPECT_EQ(ENOSPC, errno); - tfree(name); - tfree(buf); + free(name); + free(buf); } diff --git a/test/libc/fmt/palandprintf_test.c b/test/libc/fmt/palandprintf_test.c index 4c2391ff..8970f46c 100644 --- a/test/libc/fmt/palandprintf_test.c +++ b/test/libc/fmt/palandprintf_test.c @@ -626,17 +626,17 @@ TEST(xasprintf, twosBane) { TEST(snprintf, testFixedWidthString_wontOverrunInput) { const int N = 2; - char *buf = tmalloc(N + 1); - char *inp = memcpy(tmalloc(N), "hi", N); + char *buf = malloc(N + 1); + char *inp = memcpy(malloc(N), "hi", N); EXPECT_EQ(2, snprintf(buf, N + 1, "%.*s", N, inp)); EXPECT_BINEQ(u"hi ", buf); - tfree(inp); - tfree(buf); + free(inp); + free(buf); } TEST(snprintf, testFixedWidthStringIsNull_wontOverrunBuffer) { int N = 3; - char *buf = tmalloc(N + 1); + char *buf = malloc(N + 1); EXPECT_EQ(6, snprintf(buf, N + 1, "%.*s", pushpop(N), pushpop(NULL))); EXPECT_BINEQ(u"(nu ", buf); EXPECT_EQ(6, snprintf(buf, N + 1, "%#.*s", pushpop(N), pushpop(NULL))); @@ -645,12 +645,12 @@ TEST(snprintf, testFixedWidthStringIsNull_wontOverrunBuffer) { EXPECT_BINEQ(u"NUL ", buf); EXPECT_EQ(4, snprintf(buf, N + 1, "%`#.*s", pushpop(N), pushpop(NULL))); EXPECT_BINEQ(u"NUL ", buf); - tfree(buf); + free(buf); } TEST(snprintf, testFixedWidthStringIsNull_wontLeakMemory) { int N = 16; - char *buf = tmalloc(N + 1); + char *buf = malloc(N + 1); memset(buf, 0, N + 1); EXPECT_EQ(6, snprintf(buf, N + 1, "%.*s", pushpop(N), pushpop(NULL))); EXPECT_BINEQ(u"(null)           ", buf); @@ -663,7 +663,7 @@ TEST(snprintf, testFixedWidthStringIsNull_wontLeakMemory) { memset(buf, 0, N + 1); EXPECT_EQ(4, snprintf(buf, N + 1, "%`#.*s", pushpop(N), pushpop(NULL))); EXPECT_BINEQ(u"NULL             ", buf); - tfree(buf); + free(buf); } TEST(snprintf, twosBaneWithTypePromotion) { diff --git a/test/libc/fmt/test.mk b/test/libc/fmt/test.mk index eaec2dba..f44902d5 100644 --- a/test/libc/fmt/test.mk +++ b/test/libc/fmt/test.mk @@ -22,7 +22,6 @@ TEST_LIBC_FMT_DIRECTDEPS = \ LIBC_FMT \ LIBC_INTRIN \ LIBC_LOG \ - LIBC_LOG_ASAN \ LIBC_MEM \ LIBC_NEXGEN32E \ LIBC_RUNTIME \ diff --git a/test/libc/intrin/pmulhrsw_test.c b/test/libc/intrin/pmulhrsw_test.c index 6ac5bd0b..db8ee3af 100644 --- a/test/libc/intrin/pmulhrsw_test.c +++ b/test/libc/intrin/pmulhrsw_test.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "dsp/core/q.h" #include "libc/intrin/pmulhrsw.h" +#include "libc/log/check.h" #include "libc/macros.h" #include "libc/str/str.h" #include "libc/testlib/testlib.h" @@ -108,6 +109,15 @@ TEST(pmulhrsw, testFakeFloat) { } /* clang-format on */; FOR88(QD[y][x] = F2Q(15, D[y][x])); FOR88(QM[y][x] = F2Q(15, M[y][x])); + /* for (y = 0; y < 8; ++y) { */ + /* for (x = 0; x < 8; ++x) { */ + /* CHECK_NE(8, x); */ + /* CHECK_NE(8, y); */ + /* QM[y][x] = F2Q(15, M[y][x]); */ + /* CHECK_NE(8, x); */ + /* CHECK_NE(8, y); */ + /* } */ + /* } */ FOR8(pmulhrsw(QQ[y], QD[y], QM[y])); FOR88(Q[y][x] = Q2F(15, QQ[y][x])); FOR88(R[y][x] = D[y][x] * M[y][x]); diff --git a/test/libc/intrin/test.mk b/test/libc/intrin/test.mk index ff176b2c..cfe41817 100644 --- a/test/libc/intrin/test.mk +++ b/test/libc/intrin/test.mk @@ -52,10 +52,6 @@ o/$(MODE)/test/libc/intrin/%.com.dbg: \ $(APE) @$(APELINK) -# $(TEST_LIBC_INTRIN_OBJS): \ -# OVERRIDE_CFLAGS += \ -# -fsanitize=address - .PHONY: o/$(MODE)/test/libc/intrin o/$(MODE)/test/libc/intrin: \ $(TEST_LIBC_INTRIN_BINS) \ diff --git a/test/libc/nexgen32e/lz4decode_test.c b/test/libc/nexgen32e/lz4decode_test.c index 1d241995..0caf6ff5 100644 --- a/test/libc/nexgen32e/lz4decode_test.c +++ b/test/libc/nexgen32e/lz4decode_test.c @@ -19,6 +19,7 @@ #include "libc/bits/safemacros.h" #include "libc/calls/calls.h" #include "libc/log/check.h" +#include "libc/mem/mem.h" #include "libc/nexgen32e/kompressor.h" #include "libc/nexgen32e/lz4.h" #include "libc/runtime/ezmap.internal.h" @@ -30,13 +31,13 @@ TEST(lz4, decompress_emptyStringWithoutChecksum) { /* lz4 -9 --content-size --no-frame-crc /tmp/empty - | hexdump -C */ static char kLz4Data[] = {0x04, 0x22, 0x4d, 0x18, 0x60, 0x40, 0x82, 0x00, 0x00, 0x00, 0x00}; - char *src = memcpy(tmalloc(sizeof(kLz4Data)), kLz4Data, sizeof(kLz4Data)); - char *dst = tmalloc(1); + char *src = memcpy(malloc(sizeof(kLz4Data)), kLz4Data, sizeof(kLz4Data)); + char *dst = malloc(1); *dst = 'z'; ASSERT_EQ(dst, lz4decode(dst, src)); ASSERT_EQ('z', *dst); - tfree(dst); - tfree(src); + free(dst); + free(src); } TEST(lz4, decompress_oneLetterWithoutChecksum) { @@ -45,12 +46,12 @@ TEST(lz4, decompress_oneLetterWithoutChecksum) { static char kLz4Data[] = {0x04, 0x22, 0x4d, 0x18, 0x68, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x80, 0x61, 0x00, 0x00, 0x00, 0x00}; - char *src = memcpy(tmalloc(sizeof(kLz4Data)), kLz4Data, sizeof(kLz4Data)); - char *dst = tmalloc(1); + char *src = memcpy(malloc(sizeof(kLz4Data)), kLz4Data, sizeof(kLz4Data)); + char *dst = malloc(1); ASSERT_EQ(dst + 1, lz4decode(dst, src)); ASSERT_EQ('a', *dst); - tfree(dst); - tfree(src); + free(dst); + free(src); } TEST(lz4, decompress_runLengthDecode) { @@ -60,13 +61,13 @@ TEST(lz4, decompress_runLengthDecode) { 0x04, 0x22, 0x4d, 0x18, 0x68, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0b, 0x00, 0x00, 0x00, 0x1f, 0x61, 0x01, 0x00, 0x07, 0x50, 0x61, 0x61, 0x61, 0x61, 0x61, 0x00, 0x00, 0x00, 0x00}; - char *src = memcpy(tmalloc(sizeof(kLz4Data)), kLz4Data, sizeof(kLz4Data)); + char *src = memcpy(malloc(sizeof(kLz4Data)), kLz4Data, sizeof(kLz4Data)); const char *want = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - char *dst = tmalloc(strlen(want)); + char *dst = malloc(strlen(want)); ASSERT_EQ(dst + strlen(want), lz4decode(dst, src)); ASSERT_STREQN(want, dst, strlen(want)); - tfree(dst); - tfree(src); + free(dst); + free(src); } TEST(lz4, zoneFileGmt) { diff --git a/test/libc/nexgen32e/memmove_test.c b/test/libc/nexgen32e/memmove_test.c index 205cfef1..460b9e6f 100644 --- a/test/libc/nexgen32e/memmove_test.c +++ b/test/libc/nexgen32e/memmove_test.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/bits/bits.h" #include "libc/bits/safemacros.h" +#include "libc/mem/mem.h" #include "libc/str/str.h" #include "libc/testlib/testlib.h" @@ -30,14 +31,14 @@ char *b1, *b2; TEST(memmove, overlapping) { for (i = 0; i < N; i += S) { for (j = 10; j < N; j += S) { - b1 = tmalloc(N); - b2 = tmalloc(N); + b1 = malloc(N); + b2 = malloc(N); n = min(N - i, N - j); memcpy(b2, b1 + i, n); ASSERT_EQ(b1 + j, memmove(b1 + j, b1 + i, n)); ASSERT_EQ(0, memcmp(b1 + j, b2, n)); - tfree(b2); - tfree(b1); + free(b2); + free(b1); } } } @@ -45,14 +46,14 @@ TEST(memmove, overlapping) { TEST(memmove, overlappingDirect) { for (i = 0; i < N; i += S) { for (j = 10; j < N; j += S) { - b1 = tmalloc(N); - b2 = tmalloc(N); + b1 = malloc(N); + b2 = malloc(N); n = min(N - i, N - j); memcpy(b2, b1 + i, n); ASSERT_EQ(b1 + j, (memmove)(b1 + j, b1 + i, n)); ASSERT_EQ(0, memcmp(b1 + j, b2, n)); - tfree(b2); - tfree(b1); + free(b2); + free(b1); } } } diff --git a/test/libc/nexgen32e/memset_test.c b/test/libc/nexgen32e/memset_test.c index 8dba4e06..3dfbe181 100644 --- a/test/libc/nexgen32e/memset_test.c +++ b/test/libc/nexgen32e/memset_test.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/mem/mem.h" #include "libc/nexgen32e/nexgen32e.h" #include "libc/testlib/testlib.h" @@ -26,20 +27,20 @@ TEST(memset, size0_doesNothing) { } TEST(memset, size1) { - char *b = tgc(tmalloc(1)); + char *b = gc(malloc(1)); _memset(b, 7, 1); EXPECT_EQ(7, b[0]); } TEST(memset, size2) { - char *b = tgc(tmalloc(2)); + char *b = gc(malloc(2)); _memset(b, 7, 2); EXPECT_EQ(7, b[0]); EXPECT_EQ(7, b[1]); } TEST(memset, size3) { - char *b = tgc(tmalloc(3)); + char *b = gc(malloc(3)); _memset(b, 7, 3); EXPECT_EQ(7, b[0]); EXPECT_EQ(7, b[1]); @@ -47,7 +48,7 @@ TEST(memset, size3) { } TEST(memset, size4) { - char *b = tgc(tmalloc(4)); + char *b = gc(malloc(4)); _memset(b, 7, 4); EXPECT_EQ(7, b[0]); EXPECT_EQ(7, b[1]); @@ -56,7 +57,7 @@ TEST(memset, size4) { } TEST(memset, size5) { - char *b = tgc(tmalloc(5)); + char *b = gc(malloc(5)); _memset(b, 7, 5); EXPECT_EQ(7, b[0]); EXPECT_EQ(7, b[1]); @@ -70,7 +71,7 @@ TEST(memset, testMulTrick4) { unsigned long x; long di, si, dx, ax; volatile uint8_t *b; - b = tgc(tmalloc(4)); + b = gc(malloc(4)); for (i = 0; i < 255; ++i) { for (j = -1; j < 1; ++j) { x = j; @@ -93,7 +94,7 @@ TEST(memset, testMulTrick8) { unsigned long x; long di, si, dx, ax; volatile uint8_t *b; - b = tgc(tmalloc(8)); + b = gc(malloc(8)); for (i = 0; i < 255; ++i) { for (j = -1; j < 1; ++j) { x = j; diff --git a/test/libc/nexgen32e/strcaseconv_test.c b/test/libc/nexgen32e/strcaseconv_test.c index 01bc3df0..01e259e7 100644 --- a/test/libc/nexgen32e/strcaseconv_test.c +++ b/test/libc/nexgen32e/strcaseconv_test.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/mem/mem.h" #include "libc/nexgen32e/nexgen32e.h" #include "libc/rand/rand.h" #include "libc/str/str.h" @@ -23,36 +24,34 @@ #include "libc/testlib/testlib.h" TEST(strtolower, testAligned) { - EXPECT_STREQ("azcdabcdabcdabcd", - strtolower(tgc(tstrdup("AZCDabcdABCDabcd")))); + EXPECT_STREQ("azcdabcdabcdabcd", strtolower(gc(strdup("AZCDabcdABCDabcd")))); EXPECT_STREQ("azcdabcdabcdabcdabcdabcdabcdabcd", - strtolower(tgc(tstrdup("AZCDabcdABCDabcdABCDabcdABCDabcd")))); + strtolower(gc(strdup("AZCDabcdABCDabcdABCDabcdABCDabcd")))); } TEST(strtolower, testUnaligned) { - EXPECT_STREQ("1", strtolower(tgc(tstrdup("1")))); + EXPECT_STREQ("1", strtolower(gc(strdup("1")))); EXPECT_STREQ( "zcdabcdabcdabcdabcdabcdabcdabc", - strtolower((char *)tgc(tstrdup("AZCDabcdABCDabcdABCDabcdABCDabc")) + 1)); + strtolower((char *)gc(strdup("AZCDabcdABCDabcdABCDabcdABCDabc")) + 1)); } TEST(strtoupper, testAligned) { - EXPECT_STREQ("AZCDABCDABCDABCD", - strtoupper(tgc(tstrdup("AZCDabcdABCDabcd")))); + EXPECT_STREQ("AZCDABCDABCDABCD", strtoupper(gc(strdup("AZCDabcdABCDabcd")))); EXPECT_STREQ("AZCDABCDABCDABCDABCDABCDABCDABCD", - strtoupper(tgc(tstrdup("AZCDabcdABCDabcdABCDabcdABCDabcd")))); + strtoupper(gc(strdup("AZCDabcdABCDabcdABCDabcdABCDabcd")))); } TEST(strtoupper, testUnaligned) { - EXPECT_STREQ("1", strtoupper(tgc(tstrdup("1")))); + EXPECT_STREQ("1", strtoupper(gc(strdup("1")))); EXPECT_STREQ( "ZCDABCDABCDABCDABCDABCDABCDABC", - strtoupper((char *)tgc(tstrdup("AZCDabcdABCDabcdABCDabcdABCDabc")) + 1)); + strtoupper((char *)gc(strdup("AZCDabcdABCDabcdABCDabcdABCDabc")) + 1)); } BENCH(strtolower, bench) { size_t size = FRAMESIZE; - char *data = tgc(tmalloc(size)); + char *data = gc(malloc(size)); EZBENCH2( "strtolower", { diff --git a/test/libc/rand/devrand_test.c b/test/libc/rand/devrand_test.c index aa6f5897..f2730339 100644 --- a/test/libc/rand/devrand_test.c +++ b/test/libc/rand/devrand_test.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/dce.h" +#include "libc/mem/mem.h" #include "libc/rand/rand.h" #include "libc/str/str.h" #include "libc/testlib/testlib.h" @@ -24,8 +25,8 @@ TEST(devrand, test) { if (IsWindows()) return; const size_t kSize = 8; - void *A = tmalloc(kSize); - void *B = tmalloc(kSize); + void *A = malloc(kSize); + void *B = malloc(kSize); memset(A, 0, kSize); memset(B, 0, kSize); EXPECT_EQ(0, devrand(A, kSize)); @@ -33,6 +34,6 @@ TEST(devrand, test) { EXPECT_BINNE(u"        ", A); EXPECT_BINNE(u"        ", B); EXPECT_NE(0, memcmp(A, B, kSize)); - tfree(B); - tfree(A); + free(B); + free(A); } diff --git a/test/libc/rand/test.mk b/test/libc/rand/test.mk index 427367e7..54134fff 100644 --- a/test/libc/rand/test.mk +++ b/test/libc/rand/test.mk @@ -21,6 +21,7 @@ TEST_LIBC_RAND_CHECKS = \ TEST_LIBC_RAND_DIRECTDEPS = \ LIBC_FMT \ LIBC_INTRIN \ + LIBC_MEM \ LIBC_NEXGEN32E \ LIBC_RAND \ LIBC_RUNTIME \ diff --git a/test/libc/runtime/getdosargv_test.c b/test/libc/runtime/getdosargv_test.c index b781174d..ccc7e20c 100644 --- a/test/libc/runtime/getdosargv_test.c +++ b/test/libc/runtime/getdosargv_test.c @@ -16,76 +16,77 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/mem/mem.h" #include "libc/runtime/internal.h" #include "libc/testlib/testlib.h" TEST(GetDosArgv, empty) { size_t max = 4; size_t size = ARG_MAX; - char *buf = tmalloc(size * sizeof(char)); - char **argv = tmalloc(max * sizeof(char *)); + char *buf = malloc(size * sizeof(char)); + char **argv = malloc(max * sizeof(char *)); EXPECT_EQ(0, GetDosArgv(u"", buf, size, argv, max)); EXPECT_EQ(NULL, argv[0]); - tfree(argv); - tfree(buf); + free(argv); + free(buf); } TEST(GetDosArgv, emptyish) { size_t max = 4; size_t size = ARG_MAX; - char *buf = tmalloc(size * sizeof(char)); - char **argv = tmalloc(max * sizeof(char *)); + char *buf = malloc(size * sizeof(char)); + char **argv = malloc(max * sizeof(char *)); EXPECT_EQ(0, GetDosArgv(u" ", buf, size, argv, max)); EXPECT_EQ(NULL, argv[0]); - tfree(argv); - tfree(buf); + free(argv); + free(buf); } TEST(GetDosArgv, basicUsage) { size_t max = 4; size_t size = ARG_MAX; - char *buf = tmalloc(size * sizeof(char)); - char **argv = tmalloc(max * sizeof(char *)); + char *buf = malloc(size * sizeof(char)); + char **argv = malloc(max * sizeof(char *)); EXPECT_EQ(3, GetDosArgv(u"a\t \"b c\" d ", buf, size, argv, max)); EXPECT_STREQ("a", argv[0]); EXPECT_STREQ("b c", argv[1]); EXPECT_STREQ("d", argv[2]); EXPECT_EQ(NULL, argv[3]); - tfree(argv); - tfree(buf); + free(argv); + free(buf); } TEST(GetDosArgv, advancedUsage) { size_t max = 4; size_t size = ARG_MAX; - char *buf = tmalloc(size * sizeof(char)); - char **argv = tmalloc(max * sizeof(char *)); + char *buf = malloc(size * sizeof(char)); + char **argv = malloc(max * sizeof(char *)); EXPECT_EQ(2, GetDosArgv(u"(╯°□°)╯︵ ┻━┻", buf, size, argv, max)); EXPECT_STREQ("(╯°□°)╯︵", argv[0]); EXPECT_STREQ("┻━┻", argv[1]); EXPECT_EQ(NULL, argv[2]); - tfree(argv); - tfree(buf); + free(argv); + free(buf); } TEST(GetDosArgv, testAegeanGothicSupplementaryPlanes) { size_t max = 4; /* these symbols are almost as old as dos */ size_t size = ARG_MAX; - char *buf = tmalloc(size * sizeof(char)); - char **argv = tmalloc(max * sizeof(char *)); + char *buf = malloc(size * sizeof(char)); + char **argv = malloc(max * sizeof(char *)); EXPECT_EQ(2, GetDosArgv(u"𐄷𐄸𐄹𐄺𐄻𐄼 𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷", buf, size, argv, max)); EXPECT_STREQ("𐄷𐄸𐄹𐄺𐄻𐄼", argv[0]); EXPECT_STREQ("𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷", argv[1]); EXPECT_EQ(NULL, argv[2]); - tfree(argv); - tfree(buf); + free(argv); + free(buf); } TEST(GetDosArgv, realWorldUsage) { size_t max = 512; size_t size = ARG_MAX; - char *buf = tmalloc(size * sizeof(char)); - char **argv = tmalloc(max * sizeof(char *)); + char *buf = malloc(size * sizeof(char)); + char **argv = malloc(max * sizeof(char *)); EXPECT_EQ(5, GetDosArgv(u"C:\\Users\\jtunn\\printargs.com oh yes yes yes", buf, size, argv, max)); EXPECT_STREQ("C:\\Users\\jtunn\\printargs.com", argv[0]); @@ -94,21 +95,21 @@ TEST(GetDosArgv, realWorldUsage) { EXPECT_STREQ("yes", argv[3]); EXPECT_STREQ("yes", argv[4]); EXPECT_EQ(NULL, argv[5]); - tfree(argv); - tfree(buf); + free(argv); + free(buf); } TEST(GetDosArgv, bufferOverrun_countIsStillAccurate_truncatesMemoryWithGrace) { size_t max = 3; size_t size = 7; - char *buf = tmalloc(size * sizeof(char)); - char **argv = tmalloc(max * sizeof(char *)); + char *buf = malloc(size * sizeof(char)); + char **argv = malloc(max * sizeof(char *)); EXPECT_EQ(3, GetDosArgv(u"a\t \"b c\" d ", buf, size, argv, max)); EXPECT_STREQ("a", argv[0]); EXPECT_STREQ("b c", argv[1]); EXPECT_EQ(NULL, argv[2]); - tfree(argv); - tfree(buf); + free(argv); + free(buf); } TEST(GetDosArgv, pureScanningMode) { @@ -121,50 +122,50 @@ TEST(GetDosArgv, pureScanningMode) { TEST(GetDosArgv, justSlashQuote) { size_t max = 4, size = 16; - char *buf = tmalloc(size * sizeof(char)); - char **argv = tmalloc(max * sizeof(char *)); + char *buf = malloc(size * sizeof(char)); + char **argv = malloc(max * sizeof(char *)); EXPECT_EQ(1, GetDosArgv(u"\"\\\\\\\"\"", buf, size, argv, max)); EXPECT_STREQ("\\\"", argv[0]); - tfree(argv); - tfree(buf); + free(argv); + free(buf); } TEST(GetDosArgv, quoteInMiddleOfArg_wontSplitArg) { size_t max = 4, size = 16; - char *buf = tmalloc(size * sizeof(char)); - char **argv = tmalloc(max * sizeof(char *)); + char *buf = malloc(size * sizeof(char)); + char **argv = malloc(max * sizeof(char *)); EXPECT_EQ(1, GetDosArgv(u"hi\"\"there", buf, size, argv, max)); EXPECT_STREQ("hithere", argv[0]); max = 4, size = 16; EXPECT_EQ(1, GetDosArgv(u"hi\" \"there", buf, size, argv, max)); EXPECT_STREQ("hi there", argv[0]); - tfree(argv); - tfree(buf); + free(argv); + free(buf); } TEST(GetDosArgv, waqQuoting1) { size_t max = 4; size_t size = ARG_MAX; - char *buf = tmalloc(size * sizeof(char)); - char **argv = tmalloc(max * sizeof(char *)); + char *buf = malloc(size * sizeof(char)); + char **argv = malloc(max * sizeof(char *)); EXPECT_EQ(2, GetDosArgv(u"a\\\\\"\"\"\"\"\"\"\"b c\" d", buf, size, argv, max)); EXPECT_STREQ("a\\\"\"b", argv[0]); EXPECT_STREQ("c d", argv[1]); EXPECT_EQ(NULL, argv[2]); - tfree(argv); - tfree(buf); + free(argv); + free(buf); } TEST(GetDosArgv, waqQuoting2) { size_t max = 4; size_t size = ARG_MAX; - char *buf = tmalloc(size * sizeof(char)); - char **argv = tmalloc(max * sizeof(char *)); + char *buf = malloc(size * sizeof(char)); + char **argv = malloc(max * sizeof(char *)); EXPECT_EQ(2, GetDosArgv(u"\"a\\\"b c\" d", buf, size, argv, max)); EXPECT_STREQ("a\"b c", argv[0]); EXPECT_STREQ("d", argv[1]); EXPECT_EQ(NULL, argv[2]); - tfree(argv); - tfree(buf); + free(argv); + free(buf); } diff --git a/test/libc/runtime/getdosenviron_test.c b/test/libc/runtime/getdosenviron_test.c index 10a922df..4fbbf2a0 100644 --- a/test/libc/runtime/getdosenviron_test.c +++ b/test/libc/runtime/getdosenviron_test.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/mem/mem.h" #include "libc/runtime/internal.h" #include "libc/str/str.h" #include "libc/testlib/testlib.h" @@ -24,16 +25,16 @@ TEST(GetDosEnviron, testOneVariable) { #define kEnv u"A=Und wird die Welt auch in Flammen stehen\0" size_t max = 2; size_t size = sizeof(kEnv) >> 1; - char *block = tmalloc(size); - char16_t *env = memcpy(tmalloc(sizeof(kEnv)), kEnv, sizeof(kEnv)); - char **envp = tmalloc(max * sizeof(char *)); + char *block = malloc(size); + char16_t *env = memcpy(malloc(sizeof(kEnv)), kEnv, sizeof(kEnv)); + char **envp = malloc(max * sizeof(char *)); EXPECT_EQ(1, GetDosEnviron(env, block, size, envp, max)); EXPECT_STREQ("A=Und wird die Welt auch in Flammen stehen", envp[0]); EXPECT_EQ(NULL, envp[1]); ASSERT_BINEQ(u"A=Und wird die Welt auch in Flammen stehen  ", block); - tfree(envp); - tfree(env); - tfree(block); + free(envp); + free(env); + free(block); #undef kEnv } @@ -43,16 +44,16 @@ TEST(GetDosEnviron, testTwoVariables) { u"𐌴𐌵𐌶𐌷=Wir werden wieder auferstehen\0") size_t max = 3; size_t size = 1024; - char *block = tmalloc(size); - char16_t *env = memcpy(tmalloc(sizeof(kEnv)), kEnv, sizeof(kEnv)); - char **envp = tmalloc(max * sizeof(char *)); + char *block = malloc(size); + char16_t *env = memcpy(malloc(sizeof(kEnv)), kEnv, sizeof(kEnv)); + char **envp = malloc(max * sizeof(char *)); EXPECT_EQ(2, GetDosEnviron(env, block, size, envp, max)); EXPECT_STREQ("𐌰𐌱𐌲𐌳=Und wird die Welt auch in Flammen stehen", envp[0]); EXPECT_STREQ("𐌴𐌵𐌶𐌷=Wir werden wieder auferstehen", envp[1]); EXPECT_EQ(NULL, envp[2]); - tfree(envp); - tfree(env); - tfree(block); + free(envp); + free(env); + free(block); #undef kEnv } @@ -60,16 +61,16 @@ TEST(GetDosEnviron, testOverrun_truncatesWithGrace) { #define kEnv u"A=Und wird die Welt auch in Flammen stehen\0" size_t max = 2; size_t size = sizeof(kEnv) >> 2; - char *block = tmalloc(size); - char16_t *env = memcpy(tmalloc(sizeof(kEnv)), kEnv, sizeof(kEnv)); - char **envp = tmalloc(max * sizeof(char *)); + char *block = malloc(size); + char16_t *env = memcpy(malloc(sizeof(kEnv)), kEnv, sizeof(kEnv)); + char **envp = malloc(max * sizeof(char *)); EXPECT_EQ(1, GetDosEnviron(env, block, size, envp, max)); EXPECT_STREQ("A=Und wird die Welt ", envp[0]); EXPECT_EQ(NULL, envp[1]); ASSERT_BINEQ(u"A=Und wird die Welt   ", block); - tfree(envp); - tfree(env); - tfree(block); + free(envp); + free(env); + free(block); #undef kEnv } @@ -79,24 +80,24 @@ TEST(GetDosEnviron, testEmpty_doesntTouchMemory) { TEST(GetDosEnviron, testEmpty_zeroTerminatesWheneverPossible_1) { size_t max = 1; - char **envp = tmalloc(max * sizeof(char *)); + char **envp = malloc(max * sizeof(char *)); EXPECT_EQ(0, GetDosEnviron(u"", NULL, 0, envp, max)); EXPECT_EQ(NULL, envp[0]); - tfree(envp); + free(envp); } TEST(GetDosEnviron, testEmpty_zeroTerminatesWheneverPossible_2) { size_t size = 1; - char *block = tmalloc(size); + char *block = malloc(size); EXPECT_EQ(0, GetDosEnviron(u"", block, size, NULL, 0)); EXPECT_BINEQ(u" ", block); - tfree(block); + free(block); } TEST(GetDosEnviron, testEmpty_zeroTerminatesWheneverPossible_3) { size_t size = 2; - char *block = tmalloc(size); + char *block = malloc(size); EXPECT_EQ(0, GetDosEnviron(u"", block, size, NULL, 0)); EXPECT_BINEQ(u" ", block); - tfree(block); + free(block); } diff --git a/test/libc/runtime/mmap_test.c b/test/libc/runtime/mmap_test.c index 55e07d8b..9d4975a0 100644 --- a/test/libc/runtime/mmap_test.c +++ b/test/libc/runtime/mmap_test.c @@ -43,7 +43,7 @@ TEST(mmap, testMapFile) { EXPECT_EQ(5, write(fd, "hello", 5)); EXPECT_NE(-1, fdatasync(fd)); EXPECT_NE(MAP_FAILED, (p = mmap(NULL, 5, PROT_READ, MAP_PRIVATE, fd, 0))); - EXPECT_STREQ("hello", p); + EXPECT_STREQN("hello", p, 5); EXPECT_NE(-1, munmap(p, 5)); EXPECT_NE(-1, close(fd)); EXPECT_NE(-1, unlink(path)); @@ -59,7 +59,7 @@ TEST(mmap, testMapFile_fdGetsClosed_makesNoDifference) { EXPECT_NE(MAP_FAILED, (p = mmap(NULL, 5, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0))); EXPECT_NE(-1, close(fd)); - EXPECT_STREQ("hello", p); + EXPECT_STREQN("hello", p, 5); p[1] = 'a'; EXPECT_NE(-1, msync(p, PAGESIZE, MS_SYNC)); ASSERT_NE(-1, (fd = open(path, O_RDONLY))); diff --git a/test/libc/runtime/test.mk b/test/libc/runtime/test.mk index 6ba9a41a..6c3a6932 100644 --- a/test/libc/runtime/test.mk +++ b/test/libc/runtime/test.mk @@ -28,7 +28,6 @@ TEST_LIBC_RUNTIME_DIRECTDEPS = \ LIBC_FMT \ LIBC_INTRIN \ LIBC_LOG \ - LIBC_LOG_ASAN \ LIBC_MEM \ LIBC_NEXGEN32E \ LIBC_RAND \ @@ -62,12 +61,6 @@ $(TEST_LIBC_RUNTIME_OBJS): \ DEFAULT_CCFLAGS += \ -fno-builtin -# ifeq (,$(MODE)) -# $(TEST_LIBC_RUNTIME_OBJS): \ -# OVERRIDE_CFLAGS += \ -# -fsanitize=address -# endif - o/$(MODE)/test/libc/runtime/getenv_test.com.runs: \ o/$(MODE)/test/libc/runtime/getenv_test.com @HELLO=THERE build/runit $@ $< diff --git a/test/libc/sock/inet_ntop_test.c b/test/libc/sock/inet_ntop_test.c index c7bae101..f7b78ea0 100644 --- a/test/libc/sock/inet_ntop_test.c +++ b/test/libc/sock/inet_ntop_test.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/errno.h" +#include "libc/mem/mem.h" #include "libc/sock/sock.h" #include "libc/str/str.h" #include "libc/sysv/consts/af.h" @@ -44,12 +45,12 @@ TEST(inet_ntop, testBadFamily) { } TEST(inet_ntop, testNoSpace) { - char *buf = memcpy(tmalloc(16), "hi", 3); + char *buf = memcpy(malloc(16), "hi", 3); uint8_t localhost[4] = {127, 0, 0, 1}; ASSERT_EQ(NULL, inet_ntop(AF_INET, localhost, buf, 0)); EXPECT_EQ(ENOSPC, errno); ASSERT_STREQ("hi", buf); ASSERT_EQ(NULL, inet_ntop(AF_INET, localhost, buf, 7)); ASSERT_STREQ("", buf); - tfree(buf); + free(buf); } diff --git a/test/libc/sock/test.mk b/test/libc/sock/test.mk index 839da31e..aa47dc97 100644 --- a/test/libc/sock/test.mk +++ b/test/libc/sock/test.mk @@ -26,6 +26,7 @@ TEST_LIBC_SOCK_DIRECTDEPS = \ LIBC_CALLS \ LIBC_FMT \ LIBC_INTRIN \ + LIBC_MEM \ LIBC_NEXGEN32E \ LIBC_RUNTIME \ LIBC_SOCK \ diff --git a/test/libc/str/memccpy_test.c b/test/libc/str/memccpy_test.c index ae5c5cb4..3051bffe 100644 --- a/test/libc/str/memccpy_test.c +++ b/test/libc/str/memccpy_test.c @@ -16,6 +16,8 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/mem/mem.h" +#include "libc/rand/rand.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" #include "libc/testlib/ezbench.h" @@ -40,19 +42,30 @@ TEST(memccpy, testZeroLength_doesNothing) { } TEST(memccpy, memcpy) { - unsigned n, n2; + unsigned n, n1, n2; char *b1, *b2, *b3, *e1, *e2; for (n = 0; n < 1026; ++n) { - b1 = tmalloc(n); - b2 = tmalloc(n); - b3 = tmalloc(n); + b1 = calloc(1, n); + b2 = calloc(1, n); + b3 = calloc(1, n); + rngset(b1, n, rand64, -1); e1 = tinymemccpy(b2, b1, 31337, n); e2 = memccpy(b3, b1, 31337, n); - n2 = e1 ? e1 - b1 : n; - ASSERT_EQ(e1, e2); + n1 = e1 ? e1 - b2 : n; + n2 = e2 ? e2 - b3 : n; + ASSERT_LE(n1, n); + ASSERT_LE(n2, n); + ASSERT_EQ(n1, n2, + "n=%ld\r\n\t" + "n1=%8ld e1=%p b2=%p %p\r\n\t" + "n2=%8ld e2=%p b3=%p %p\r\n\t" + "%#.*s\r\n\t" + "%#.*s\r\n\t" + "%#.*s", + n, n1, e1, b2, e1 - b2, n2, e2, b3, e2 - b3, n, b1, n, b2, n, b3); ASSERT_EQ(0, memcmp(b2, b3, n2)); - tfree(b3); - tfree(b2); - tfree(b1); + free(b3); + free(b2); + free(b1); } } diff --git a/test/libc/str/memcpy_test.c b/test/libc/str/memcpy_test.c index 3c517c28..2181c428 100644 --- a/test/libc/str/memcpy_test.c +++ b/test/libc/str/memcpy_test.c @@ -24,61 +24,61 @@ TEST(memcpy, memcpy) { char *b1, *b2; for (unsigned n = 0; n < 1026; ++n) { - b1 = tmalloc(n); - b2 = tmalloc(n); + b1 = malloc(n); + b2 = malloc(n); ASSERT_EQ(b1, memcpy(b1, b2, n)); ASSERT_EQ(0, memcmp(b1, b2, n)); - tfree(b2); - tfree(b1); + free(b2); + free(b1); } } TEST(memcpy, memcpyDirect) { char *b1, *b2; for (unsigned n = 0; n < 1026; ++n) { - b1 = tmalloc(n); - b2 = tmalloc(n); + b1 = malloc(n); + b2 = malloc(n); ASSERT_EQ(b1, (memcpy)(b1, b2, n)); ASSERT_EQ(0, memcmp(b1, b2, n)); - tfree(b2); - tfree(b1); + free(b2); + free(b1); } } TEST(memcpy, mempcpy) { char *b1, *b2; for (unsigned n = 0; n < 1026; ++n) { - b1 = tmalloc(n); - b2 = tmalloc(n); + b1 = malloc(n); + b2 = malloc(n); ASSERT_EQ(b1 + n, mempcpy(b1, b2, n)); ASSERT_EQ(0, memcmp(b1, b2, n)); - tfree(b2); - tfree(b1); + free(b2); + free(b1); } } TEST(memcpy, mempcpyDirect) { char *b1, *b2; for (unsigned n = 0; n < 1026; ++n) { - b1 = tmalloc(n); - b2 = tmalloc(n); + b1 = malloc(n); + b2 = malloc(n); ASSERT_EQ(b1 + n, (mempcpy)(b1, b2, n)); ASSERT_EQ(0, memcmp(b1, b2, n)); - tfree(b2); - tfree(b1); + free(b2); + free(b1); } } TEST(memcpy, overlapping_isFineIfCopyingBackwards) { for (size_t i = 0; i < 32; ++i) { - char *b1 = tmalloc(64 + i); - char *b2 = tmalloc(64 + i); + char *b1 = malloc(64 + i); + char *b2 = malloc(64 + i); memcpy(b1, b2, 64); memcpy(b1, b1 + i, 64 - i); memmove(b2, b2 + i, 64 - i); ASSERT_EQ(0, memcmp(b1, b2, 64)); - tfree(b2); - tfree(b1); + free(b2); + free(b1); } } diff --git a/test/libc/str/memmem_test.c b/test/libc/str/memmem_test.c index ba9889e6..21478b10 100644 --- a/test/libc/str/memmem_test.c +++ b/test/libc/str/memmem_test.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/alg/alg.h" #include "libc/bits/bits.h" +#include "libc/mem/mem.h" #include "libc/str/internal.h" #include "libc/str/str.h" #include "libc/testlib/testlib.h" @@ -27,7 +28,7 @@ FIXTURE(memmem, tiny) { memmemi = tinymemmem; } -#define MakeMemory(SL) memcpy(tmalloc(sizeof(SL) - 1), SL, sizeof(SL) - 1) +#define MakeMemory(SL) memcpy(malloc(sizeof(SL) - 1), SL, sizeof(SL) - 1) TEST(memmem, test) { char *needle = MakeMemory("abcdefgh"); @@ -36,40 +37,40 @@ TEST(memmem, test) { memcpy(needle, "aaaaaaaa", 8); memcpy(haystk, "acccccccbbbbbbbbaaaaaaaadddddddd", 32); EXPECT_BINEQ(u"aaaaaaaadddddddd", memmemi(haystk, 32, needle, 8)); - tfree(haystk); - tfree(needle); + free(haystk); + free(needle); } TEST(memmem, testNoMatch) { char *needle = MakeMemory("abcdefzh"); char *haystk = MakeMemory("acccccccbbbbbbbbabcdefghdddddddd"); EXPECT_EQ(NULL, memmemi(haystk, 32, needle, 8)); - tfree(haystk); - tfree(needle); + free(haystk); + free(needle); } TEST(memmem, testStartOfMemory) { char *needle = MakeMemory("acccc"); char *haystk = MakeMemory("acccccccbbbbbbbbabcdefghdddddddd"); EXPECT_EQ(&haystk[0], memmemi(haystk, 32, needle, 5)); - tfree(haystk); - tfree(needle); + free(haystk); + free(needle); } TEST(memmem, testEndOfMemory) { char *needle = MakeMemory("123"); char *haystk = MakeMemory("abc123"); EXPECT_EQ(&haystk[3], memmemi(haystk, 6, needle, 3)); - tfree(haystk); - tfree(needle); + free(haystk); + free(needle); } TEST(memmem, testCrossesSseRegister) { char *needle = MakeMemory("eeeeeeeeeeeeefffffffffffff"); char *haystk = MakeMemory("eeeeeeeeeeeeeeeeffffffffffffffffrrrrrrrrrrrrrrrr"); EXPECT_EQ(&haystk[3], memmemi(haystk, 16 * 3, needle, 26)); - tfree(haystk); - tfree(needle); + free(haystk); + free(needle); } TEST(memmem, testHasNulCharacters) { @@ -77,39 +78,39 @@ TEST(memmem, testHasNulCharacters) { char *haystk = MakeMemory("eeeeeeeeeeeeeeee\0fffffffffffffffrrrrrrrrrrrrrrrr"); EXPECT_EQ(&haystk[3], memmemi(haystk, 16 * 3, needle, 26)); - tfree(haystk); - tfree(needle); + free(haystk); + free(needle); } TEST(memmem, testWeird) { char *needle = MakeMemory("-*-+-+-+-+-+-+-+"); char *haystk = MakeMemory("-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-+"); EXPECT_EQ(14, (intptr_t)memmemi(haystk, 32, needle, 16) - (intptr_t)haystk); - tfree(haystk); - tfree(needle); + free(haystk); + free(needle); } TEST(memmem, testEmptyNeedle_matchesStartOfHaystack) { - char *needle = tmalloc(0); + char *needle = malloc(0); char *haystk = MakeMemory("-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-+"); EXPECT_EQ(0, (intptr_t)memmemi(haystk, 32, needle, 0) - (intptr_t)haystk); - tfree(haystk); - tfree(needle); + free(haystk); + free(needle); } TEST(memmem, testEmptyHaystack_alwaysReturnsNull) { char *needle = MakeMemory("-*-+-+-+-+-+-+-+"); - char *haystk = tmalloc(0); + char *haystk = malloc(0); EXPECT_EQ(NULL, memmemi(haystk, 0, needle, 16)); EXPECT_EQ(NULL, memmemi(haystk, 0, needle, 1)); - tfree(haystk); - tfree(needle); + free(haystk); + free(needle); } TEST(memmem, testEmptyHaystackAndNeedle_returnsHaystack) { - char *needle = tmalloc(0); - char *haystk = tmalloc(0); + char *needle = malloc(0); + char *haystk = malloc(0); EXPECT_EQ(haystk, memmemi(haystk, 0, needle, 0)); - tfree(haystk); - tfree(needle); + free(haystk); + free(needle); } diff --git a/test/libc/str/pututf16_test.c b/test/libc/str/pututf16_test.c index e68e0c41..88322a13 100644 --- a/test/libc/str/pututf16_test.c +++ b/test/libc/str/pututf16_test.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/bits/bits.h" +#include "libc/mem/mem.h" #include "libc/str/oldutf16.internal.h" #include "libc/str/str.h" #include "libc/testlib/testlib.h" @@ -34,38 +35,38 @@ TEST(pututf16, testEmpty) { TEST(pututf16, testNul) { size = 1; - buf = tmalloc(size * sizeof(char16_t)); + buf = malloc(size * sizeof(char16_t)); EXPECT_EQ(1, pututf16(buf, size, u'\0', false)); EXPECT_EQ(u'\0', buf[0]); buf[0] = '\7'; EXPECT_EQ(1, (pututf16)(buf, size, u'\0', false)); EXPECT_EQ(u'\0', buf[0]); - tfree(buf); + free(buf); } TEST(pututf16, testAscii) { size = 1; - buf = tmalloc(size * sizeof(char16_t)); + buf = malloc(size * sizeof(char16_t)); EXPECT_EQ(1, pututf16(buf, size, u'j', false)); EXPECT_EQ(u'j', buf[0]); EXPECT_EQ(1, (pututf16)(buf, size, u't', false)); EXPECT_EQ(u't', buf[0]); - tfree(buf); + free(buf); } TEST(pututf16, testGothicSupplementaryPlane) { size = 2; - buf = tmalloc(size * sizeof(char16_t)); + buf = malloc(size * sizeof(char16_t)); EXPECT_EQ(2, pututf16(buf, size, L'𐌰', false)); EXPECT_STREQN(u"𐌰", buf, 1); EXPECT_EQ(2, (pututf16)(buf, size, L'𐌱', false)); EXPECT_STREQN(u"𐌱", buf, 1); - tfree(buf); + free(buf); } TEST(pututf16, testEmojiAndEmojiPresentationModifier_areBothInAstralPlanes) { n = 8; - b = tgc(tmalloc(sizeof(char16_t) * n)); + b = gc(malloc(sizeof(char16_t) * n)); str = L"\U0001F466\U0001F3FF"; memset(b, 0, n * sizeof(char16_t)); EXPECT_EQ(2, pututf16(b, n, str[0], false)); diff --git a/test/libc/str/strcmp_test.c b/test/libc/str/strcmp_test.c index f2db9d84..4c34f2e3 100644 --- a/test/libc/str/strcmp_test.c +++ b/test/libc/str/strcmp_test.c @@ -19,9 +19,11 @@ #include "libc/bits/bits.h" #include "libc/dce.h" #include "libc/macros.h" +#include "libc/mem/mem.h" #include "libc/nexgen32e/cachesize.h" #include "libc/nexgen32e/x86feature.h" #include "libc/rand/rand.h" +#include "libc/runtime/gc.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" #include "libc/testlib/ezbench.h" @@ -64,27 +66,27 @@ TEST(wcscasecmp, emptyString) { } TEST(strncmp, emptyString) { - char *s1 = strcpy(tmalloc(1), ""); - char *s2 = strcpy(tmalloc(1), ""); + char *s1 = strcpy(malloc(1), ""); + char *s2 = strcpy(malloc(1), ""); ASSERT_EQ(0, strncmp(s1, s2, 0)); ASSERT_EQ(0, strncmp(s1, s2, 1)); ASSERT_EQ(0, strncmp(s1, s2, -1)); ASSERT_EQ(0, strncmp(s1, s1, -1)); ASSERT_EQ(0, strncmp(s2, s2, -1)); - tfree(s2); - tfree(s1); + free(s2); + free(s1); } TEST(strncasecmp, emptyString) { - char *s1 = strcpy(tmalloc(1), ""); - char *s2 = strcpy(tmalloc(1), ""); + char *s1 = strcpy(malloc(1), ""); + char *s2 = strcpy(malloc(1), ""); ASSERT_EQ(0, strncasecmp(s1, s2, 0)); ASSERT_EQ(0, strncasecmp(s1, s2, 1)); ASSERT_EQ(0, strncasecmp(s1, s2, -1)); ASSERT_EQ(0, strncasecmp(s1, s1, -1)); ASSERT_EQ(0, strncasecmp(s2, s2, -1)); - tfree(s2); - tfree(s1); + free(s2); + free(s1); } /*───────────────────────────────────────────────────────────────────────────│─╗ @@ -92,13 +94,13 @@ TEST(strncasecmp, emptyString) { ╚────────────────────────────────────────────────────────────────────────────│*/ TEST(strncmp, testInequality) { - char *s1 = strcpy(tmalloc(2), "1"); - char *s2 = strcpy(tmalloc(1), ""); + char *s1 = strcpy(malloc(2), "1"); + char *s2 = strcpy(malloc(1), ""); ASSERT_EQ(0, strncmp(s1, s2, 0)); ASSERT_EQ('1', strncmp(s1, s2, 1)); ASSERT_EQ(-'1', strncmp(s2, s1, 1)); - tfree(s2); - tfree(s1); + free(s2); + free(s1); } /*───────────────────────────────────────────────────────────────────────────│─╗ @@ -318,8 +320,8 @@ TEST(strcasecmp8to16, testItWorksCase) { ╚────────────────────────────────────────────────────────────────────────────│*/ TEST(strncmp, testEqualManyNs) { - char *s1 = tmalloc(PAGESIZE); - char *s2 = tmalloc(PAGESIZE); + char *s1 = malloc(PAGESIZE); + char *s2 = malloc(PAGESIZE); memset(s1, 7, PAGESIZE); memset(s2, 7, PAGESIZE); s1[PAGESIZE - 1] = '\0'; @@ -328,13 +330,13 @@ TEST(strncmp, testEqualManyNs) { ASSERT_EQ(0, strncmp(s1 + PAGESIZE - i, s2 + PAGESIZE - i, i + 0)); ASSERT_EQ(0, strncmp(s1 + PAGESIZE - i, s2 + PAGESIZE - i, i + 1)); } - tfree(s2); - tfree(s1); + free(s2); + free(s1); } TEST(strncmp, testNotEqualManyNs) { - char *s1 = tmalloc(PAGESIZE); - char *s2 = tmalloc(PAGESIZE); + char *s1 = malloc(PAGESIZE); + char *s2 = malloc(PAGESIZE); for (unsigned i = 1; i <= 128; ++i) { memset(s1, 7, PAGESIZE); memset(s2, 7, PAGESIZE); @@ -343,8 +345,8 @@ TEST(strncmp, testNotEqualManyNs) { ASSERT_EQ(-255, strncmp(s1 + PAGESIZE - i, s2 + PAGESIZE - i, i + 0)); ASSERT_EQ(-255, strncmp(s1 + PAGESIZE - i, s2 + PAGESIZE - i, i + 1)); } - tfree(s2); - tfree(s1); + free(s2); + free(s1); } /*───────────────────────────────────────────────────────────────────────────│─╗ @@ -354,40 +356,40 @@ TEST(strncmp, testNotEqualManyNs) { TEST(strncmp, testStringNulTerminatesBeforeExplicitLength) { const char kRdi[] = ""; const char kRsi[] = "TZ=America/Los_Angeles"; - char *rdi = memcpy(tmalloc(sizeof(kRdi)), kRdi, sizeof(kRdi)); - char *rsi = memcpy(tmalloc(sizeof(kRsi)), kRsi, sizeof(kRsi)); + char *rdi = memcpy(malloc(sizeof(kRdi)), kRdi, sizeof(kRdi)); + char *rsi = memcpy(malloc(sizeof(kRsi)), kRsi, sizeof(kRsi)); size_t rdx = 3; EXPECT_EQ(strncmp(rdi, rdi, rdx), 0); EXPECT_LT(strncmp(rdi, rsi, rdx), 0); EXPECT_GT(strncmp(rsi, rdi, rdx), 0); - tfree(rsi); - tfree(rdi); + free(rsi); + free(rdi); } TEST(strncasecmp, testStringNulTerminatesBeforeExplicitLength) { const char kRdi[] = ""; const char kRsi[] = "TZ=America/Los_Angeles"; - char *rdi = memcpy(tmalloc(sizeof(kRdi)), kRdi, sizeof(kRdi)); - char *rsi = memcpy(tmalloc(sizeof(kRsi)), kRsi, sizeof(kRsi)); + char *rdi = memcpy(malloc(sizeof(kRdi)), kRdi, sizeof(kRdi)); + char *rsi = memcpy(malloc(sizeof(kRsi)), kRsi, sizeof(kRsi)); size_t rdx = 3; EXPECT_EQ(strncasecmp(rdi, rdi, rdx), 0); EXPECT_LT(strncasecmp(rdi, rsi, rdx), 0); EXPECT_GT(strncasecmp(rsi, rdi, rdx), 0); - tfree(rsi); - tfree(rdi); + free(rsi); + free(rdi); } TEST(strncmp16, testStringNulTerminatesBeforeExplicitLength) { const char16_t kRdi[] = u""; const char16_t kRsi[] = u"TZ=America/Los_Angeles"; - char16_t *rdi = memcpy(tmalloc(sizeof(kRdi)), kRdi, sizeof(kRdi)); - char16_t *rsi = memcpy(tmalloc(sizeof(kRsi)), kRsi, sizeof(kRsi)); + char16_t *rdi = memcpy(malloc(sizeof(kRdi)), kRdi, sizeof(kRdi)); + char16_t *rsi = memcpy(malloc(sizeof(kRsi)), kRsi, sizeof(kRsi)); size_t rdx = 3; EXPECT_EQ(strncmp16(rdi, rdi, rdx), 0); EXPECT_LT(strncmp16(rdi, rsi, rdx), 0); EXPECT_GT(strncmp16(rsi, rdi, rdx), 0); - tfree(rsi); - tfree(rdi); + free(rsi); + free(rdi); } /*───────────────────────────────────────────────────────────────────────────│─╗ @@ -422,33 +424,33 @@ TEST(memcmp, testTwosComplementBane_unsignedBehavior) { } TEST(strcmp16, testTwosComplementBane_hasUnsignedBehavior) { - char16_t *B1 = tmalloc(8); - char16_t *B2 = tmalloc(8); + char16_t *B1 = malloc(8); + char16_t *B2 = malloc(8); B1[1] = L'\0'; B2[1] = L'\0'; EXPECT_EQ(strcmp16(memcpy(B1, "\x00\x80", 2), memcpy(B2, "\x00\x80", 2)), 0); EXPECT_LT(strcmp16(memcpy(B1, "\xff\x7f", 2), memcpy(B2, "\x00\x80", 2)), 0); EXPECT_GT(strcmp16(memcpy(B1, "\x00\x80", 2), memcpy(B2, "\xff\x7f", 2)), 0); - tfree(B2); - tfree(B1); + free(B2); + free(B1); } TEST(strncmp16, testTwosComplementBane_hasUnsignedBehavior) { - char16_t *B1 = tmalloc(4); - char16_t *B2 = tmalloc(4); + char16_t *B1 = malloc(4); + char16_t *B2 = malloc(4); EXPECT_EQ(strncmp16(memcpy(B1, "\x00\x80", 2), memcpy(B2, "\x00\x80", 2), 1), 0); EXPECT_LT(strncmp16(memcpy(B1, "\xff\x7f", 2), memcpy(B2, "\x00\x80", 2), 1), 0); EXPECT_GT(strncmp16(memcpy(B1, "\x00\x80", 2), memcpy(B2, "\xff\x7f", 2), 1), 0); - tfree(B2); - tfree(B1); + free(B2); + free(B1); } TEST(wcscmp, testTwosComplementBane) { - wchar_t *B1 = tmalloc(8); - wchar_t *B2 = tmalloc(8); + wchar_t *B1 = malloc(8); + wchar_t *B2 = malloc(8); B1[1] = L'\0'; B2[1] = L'\0'; EXPECT_EQ(wcscmp(memcpy(B1, "\x00\x00\x00\x80", 4), @@ -459,13 +461,13 @@ TEST(wcscmp, testTwosComplementBane) { EXPECT_EQ(wcscmp(memcpy(B1, "\x00\x00\x00\x80", 4), memcpy(B2, "\xff\xff\xff\x7f", 4)), 1); - tfree(B2); - tfree(B1); + free(B2); + free(B1); } TEST(wcsncmp, testTwosComplementBane) { - wchar_t *B1 = tmalloc(4); - wchar_t *B2 = tmalloc(4); + wchar_t *B1 = malloc(4); + wchar_t *B2 = malloc(4); EXPECT_EQ(wcsncmp(memcpy(B1, "\x00\x00\x00\x80", 4), memcpy(B2, "\x00\x00\x00\x80", 4), 1), 0); @@ -475,8 +477,8 @@ TEST(wcsncmp, testTwosComplementBane) { EXPECT_EQ(wcsncmp(memcpy(B1, "\x00\x00\x00\x80", 4), memcpy(B2, "\xff\xff\xff\x7f", 4), 1), 1); - tfree(B2); - tfree(B1); + free(B2); + free(B1); } /*───────────────────────────────────────────────────────────────────────────│─╗ @@ -530,8 +532,8 @@ BENCH(bench_00_strcmp, bench) { char *dupe, *data; size = ROUNDDOWN(MAX(FRAMESIZE, getcachesize(kCpuCacheTypeData, 1)) / 2, PAGESIZE); - data = tgc(tmalloc(size)); - dupe = tgc(tmalloc(size)); + data = gc(malloc(size)); + dupe = gc(malloc(size)); fprintf(stderr, "\n"); EZBENCH2("strcmp [identity]", longstringislong(size, data), @@ -579,8 +581,8 @@ BENCH(bench_01_strcasecmp, bench) { char *dupe, *data; size = ROUNDDOWN(MAX(FRAMESIZE, getcachesize(kCpuCacheTypeData, 1)) / 2, PAGESIZE); - data = tgc(tmalloc(size)); - dupe = tgc(tmalloc(size)); + data = gc(malloc(size)); + dupe = gc(malloc(size)); fprintf(stderr, "\n"); EZBENCH2("strcasecmp [identity]", longstringislong(size, data), diff --git a/test/libc/str/strlen_test.c b/test/libc/str/strlen_test.c index d0399e31..b874bd6e 100644 --- a/test/libc/str/strlen_test.c +++ b/test/libc/str/strlen_test.c @@ -18,7 +18,9 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/bits/bits.h" #include "libc/macros.h" +#include "libc/mem/mem.h" #include "libc/nexgen32e/tinystrlen.internal.h" +#include "libc/rand/rand.h" #include "libc/str/str.h" #include "libc/testlib/ezbench.h" #include "libc/testlib/testlib.h" @@ -88,10 +90,10 @@ TEST(strnlen_s, null_ReturnsZero) { TEST(strnlen, nulNotFound_ReturnsSize) { int sizes[] = {1, 2, 7, 8, 15, 16, 31, 32, 33}; for (unsigned i = 0; i < ARRAYLEN(sizes); ++i) { - char *buf = tmalloc(sizes[i]); + char *buf = malloc(sizes[i]); memset(buf, ' ', sizes[i]); ASSERT_EQ(sizes[i], strnlen(buf, sizes[i]), "%d", sizes[i]); - tfree(buf); + free(buf); } } @@ -134,15 +136,38 @@ TEST(tinystrnlen16, test) { EXPECT_EQ(3, tinystrnlen16(u"123", 4)); } +TEST(strlen, fuzz) { + char *b; + size_t n, n1, n2; + for (n = 2; n < 1026; ++n) { + b = rngset(calloc(1, n), n - 1, rand64, -1); + n1 = strlen(b); + n2 = strlen$pure(b); + ASSERT_EQ(n1, n2); + n1 = strlen(b + 1); + n2 = strlen$pure(b + 1); + ASSERT_EQ(n1, n2); + free(b); + } +} + BENCH(strlen, bench) { extern size_t strlen_(const char *) asm("strlen"); + extern size_t strlen$pure_(const char *) asm("strlen$pure"); static char b[2048]; memset(b, -1, sizeof(b) - 1); EZBENCH2("strlen 1", donothing, strlen_("")); + EZBENCH2("strlen$pure 1", donothing, strlen$pure_("")); EZBENCH2("strlen 2", donothing, strlen_("1")); + EZBENCH2("strlen$pure 2", donothing, strlen$pure_("1")); EZBENCH2("strlen 7", donothing, strlen_("123456")); + EZBENCH2("strlen$pure 7", donothing, strlen$pure_("123456")); EZBENCH2("strlen 8", donothing, strlen_("1234567")); + EZBENCH2("strlen$pure 8", donothing, strlen$pure_("1234567")); EZBENCH2("strlen 9", donothing, strlen_("12345678")); + EZBENCH2("strlen$pure 9", donothing, strlen$pure_("12345678")); EZBENCH2("strlen 16", donothing, strlen_("123456781234567")); + EZBENCH2("strlen$pure 16", donothing, strlen$pure_("123456781234567")); EZBENCH2("strlen 1023", donothing, strlen_(b)); + EZBENCH2("strlen$pure 1023", donothing, strlen$pure_(b)); } diff --git a/test/libc/str/strstr_test.c b/test/libc/str/strstr_test.c index 2d1ea6ab..639b158e 100644 --- a/test/libc/str/strstr_test.c +++ b/test/libc/str/strstr_test.c @@ -26,7 +26,7 @@ #include "libc/testlib/testlib.h" #define MAKESTRING(NAME, VALUE) \ - char *NAME = strcpy(tmalloc(sizeof(VALUE) + 16), VALUE) + char *NAME = strcpy(malloc(sizeof(VALUE) + 16), VALUE) char *strstr$kmp(const char *haystak, const char *needle) { return memmem(haystak, strlen(haystak), needle, strlen(needle)); @@ -44,40 +44,40 @@ TEST(strstr, test_emptyString_isFoundAtBeginning) { MAKESTRING(haystack, "abc123def"); ASSERT_STREQ(&haystack[0], strstri(haystack, gc(strdup("")))); ASSERT_STREQ(&haystack[0], strstr(haystack, gc(strdup("")))); - tfree(haystack); + free(haystack); } TEST(strstr, test_notFound) { MAKESTRING(haystack, "abc123def"); ASSERT_EQ(NULL, strstri(haystack, gc(strdup("xyz")))); ASSERT_EQ(NULL, strstr(haystack, gc(strdup("xyz")))); - tfree(haystack); + free(haystack); } TEST(strstr, test_middleOfString) { MAKESTRING(haystack, "abc123def"); ASSERT_STREQ(&haystack[3], strstri(haystack, gc(strdup("123")))); ASSERT_STREQ(&haystack[3], strstr(haystack, gc(strdup("123")))); - tfree(haystack); + free(haystack); } TEST(strstr, test_endOfString) { MAKESTRING(haystack, "abc123def"); ASSERT_STREQ(&haystack[8], strstri(haystack, gc(strdup("f")))); ASSERT_STREQ(&haystack[8], strstr(haystack, gc(strdup("f")))); - tfree(haystack); + free(haystack); } TEST(strstr, test_secondXmmWord) { MAKESTRING(haystack, "eeeeeeeeeeeeeeeebbbbbbbbbbb123"); ASSERT_STREQ(&haystack[27], strstri(haystack, gc(strdup("123")))); ASSERT_STREQ(&haystack[27], strstr(haystack, gc(strdup("123")))); - tfree(haystack); + free(haystack); } TEST(strstr, test_overlapsXmmWords) { MAKESTRING(haystack, "eeeeeeeeeeeeeeeebbbbbbbbbbbbbbb"); ASSERT_STREQ(&haystack[15], strstri(haystack, gc(strdup("eb")))); ASSERT_STREQ(&haystack[15], strstr(haystack, gc(strdup("eb")))); - tfree(haystack); + free(haystack); } diff --git a/test/libc/str/strtok_r_test.c b/test/libc/str/strtok_r_test.c index 0978acbf..215c03ab 100644 --- a/test/libc/str/strtok_r_test.c +++ b/test/libc/str/strtok_r_test.c @@ -16,49 +16,50 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/mem/mem.h" #include "libc/str/str.h" #include "libc/testlib/testlib.h" TEST(strtok_r, testEmpty) { static const char *const kInput = ""; static const char *const kSeparators = "/"; - char *s = strcpy(tmalloc(strlen(kInput) + 1), kInput); + char *s = strcpy(malloc(strlen(kInput) + 1), kInput); char *state; EXPECT_EQ(NULL, strtok_r(s, kSeparators, &state)); - tfree(s); + free(s); } TEST(strtok_r, test) { static const char *const kInput = ".,lol..cat.."; static const char *const kSeparators = ".,"; - char *s = strcpy(tmalloc(strlen(kInput) + 1), kInput); + char *s = strcpy(malloc(strlen(kInput) + 1), kInput); char *state; EXPECT_STREQ("lol", strtok_r(s, kSeparators, &state)); EXPECT_STREQ("cat", strtok_r(NULL, kSeparators, &state)); EXPECT_EQ(NULL, strtok_r(NULL, kSeparators, &state)); EXPECT_EQ(NULL, strtok_r(NULL, kSeparators, &state)); - tfree(s); + free(s); } TEST(strtok, test) { static const char *const kInput = ".,lol..cat.."; static const char *const kSeparators = ".,"; - char *s = strcpy(tmalloc(strlen(kInput) + 1), kInput); + char *s = strcpy(malloc(strlen(kInput) + 1), kInput); EXPECT_STREQ("lol", strtok(s, kSeparators)); EXPECT_STREQ("cat", strtok(NULL, kSeparators)); EXPECT_EQ(NULL, strtok(NULL, kSeparators)); EXPECT_EQ(NULL, strtok(NULL, kSeparators)); - tfree(s); + free(s); } TEST(strtok_r, testHostsTxtLine) { static const char *const kInput = "203.0.113.1 lol.example. lol"; static const char *const kSeparators = " \t"; - char *s = strcpy(tmalloc(strlen(kInput) + 1), kInput); + char *s = strcpy(malloc(strlen(kInput) + 1), kInput); char *state; EXPECT_STREQ("203.0.113.1", strtok_r(s, kSeparators, &state)); EXPECT_STREQ("lol.example.", strtok_r(NULL, kSeparators, &state)); EXPECT_STREQ("lol", strtok_r(NULL, kSeparators, &state)); EXPECT_EQ(NULL, strtok_r(NULL, kSeparators, &state)); - tfree(s); + free(s); } diff --git a/test/libc/str/tprecode16to8_test.c b/test/libc/str/tprecode16to8_test.c index a0e118d8..e0490b9e 100644 --- a/test/libc/str/tprecode16to8_test.c +++ b/test/libc/str/tprecode16to8_test.c @@ -47,11 +47,11 @@ TEST(tprecode16to8, testTooLittle_stillNulTerminates) { TEST(tprecode16to8, testAscii_vectorSpeedupWorks) { size_t size = 32; - char *buf = tmalloc(size); + char *buf = malloc(size); EXPECT_EQ(31, tprecode16to8(buf, size, u"babaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").ax); EXPECT_STREQ("babaaaaaaaaaaaaaaaaaaaaaaaaaaaa", buf); - tfree(buf); + free(buf); } BENCH(tprecode16to8, bench) { diff --git a/test/libc/str/tprecode8to16_test.c b/test/libc/str/tprecode8to16_test.c index 781cee24..d08af384 100644 --- a/test/libc/str/tprecode8to16_test.c +++ b/test/libc/str/tprecode8to16_test.c @@ -25,10 +25,10 @@ TEST(tprecode8to16, test) { size_t size = 8; - char16_t *buf = tmalloc(size * sizeof(char16_t)); + char16_t *buf = malloc(size * sizeof(char16_t)); EXPECT_EQ(7, tprecode8to16(buf, size, "hello☻♥").ax); EXPECT_STREQ(u"hello☻♥", buf); - tfree(buf); + free(buf); } TEST(tprecode8to16, testEmptyOut_doesNothingButStillCountsSrcLength) { @@ -65,11 +65,11 @@ TEST(tprecode8to16, test2) { TEST(tprecode8to16, testAscii_vectorSpeedupWorks) { size_t size = 32; - char16_t *buf = tmalloc(size * sizeof(char16_t)); + char16_t *buf = malloc(size * sizeof(char16_t)); EXPECT_EQ(31, tprecode8to16(buf, size, "babaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").ax); EXPECT_STREQ(u"babaaaaaaaaaaaaaaaaaaaaaaaaaaaa", buf); - tfree(buf); + free(buf); } BENCH(tprecode8to16, bench) { diff --git a/test/libc/runtime/gc_test.c b/test/libc/tinymath/exp_test.c similarity index 56% rename from test/libc/runtime/gc_test.c rename to test/libc/tinymath/exp_test.c index 28d1ac58..28d24d43 100644 --- a/test/libc/runtime/gc_test.c +++ b/test/libc/tinymath/exp_test.c @@ -16,65 +16,14 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/calls.h" -#include "libc/mem/mem.h" +#include "libc/math.h" #include "libc/runtime/gc.h" -#include "libc/runtime/runtime.h" -#include "libc/str/str.h" -#include "libc/sysv/consts/o.h" +#include "libc/stdio/stdio.h" #include "libc/testlib/testlib.h" #include "libc/x/x.h" -/* TODO(jart): calling malloc_usable_size was a terrible idea */ - -TEST(todo_jart, broken_in_opt_native_mode) { - (void)0; - (void)0; -} - -int64_t fd; - -TEST(gc, usageExample_c11) { - fd = open("/dev/null", O_WRONLY); - defer(close_s, &fd); - char *msg = gc(xasprintf("%d + %d = %d", 2, 2, 2 + 2)); - write(fd, msg, strlen(msg)); -} - -TEST(gc, checkMallocUsableSizeWorksTheWayWeHopeItDoes) { - char *p = malloc(32); - EXPECT_GE(malloc_usable_size(p), 32); - free(p); - EXPECT_GE(malloc_usable_size(p), 0); -} - -noinline void function1of1(char *p) { - EXPECT_GE(malloc_usable_size(gc(p)), 32); -} -TEST(gc, testOne) { - char *p = malloc(32); - function1of1(p); - EXPECT_EQ(malloc_usable_size(p), 0); -} - -noinline void function2of2(char *p1, char *p2) { - EXPECT_GE(malloc_usable_size(p1), 32); - EXPECT_GE(malloc_usable_size(p2), 64); - gc(p2); - EXPECT_GE(malloc_usable_size(p1), 32); - EXPECT_GE(malloc_usable_size(p2), 64); -} -noinline void function1of2(char *p1, char *p2) { - EXPECT_GE(malloc_usable_size(p1), 32); - EXPECT_GE(malloc_usable_size(p2), 64); - function2of2(gc(p1), p2); - EXPECT_GE(malloc_usable_size(p1), 32); - EXPECT_GE(malloc_usable_size(p2), 0); -} -TEST(gc, testTwo) { - char *p1 = malloc(32); - char *p2 = malloc(64); - function1of2(p1, p2); - EXPECT_GE(malloc_usable_size(p1), 0); - EXPECT_GE(malloc_usable_size(p2), 0); +TEST(exp, test) { + ASSERT_STREQ("7.389056", gc(xasprintf("%f", exp(2.0)))); + ASSERT_STREQ("6.389056", gc(xasprintf("%f", expm1(2.0)))); + ASSERT_STREQ("6.389056", gc(xasprintf("%f", exp(2.0) - 1.0))); } diff --git a/test/libc/tinymath/ilogb_test.c b/test/libc/tinymath/ilogb_test.c new file mode 100644 index 00000000..e91a851d --- /dev/null +++ b/test/libc/tinymath/ilogb_test.c @@ -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 2020 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/math.h" +#include "libc/testlib/testlib.h" + +TEST(ilogb, test) { + /* TODO(jart): this */ + /* EXPECT_EQ(0x7fffffff, ilogb(INFINITY)); */ + EXPECT_EQ(0, ilogb(1)); + EXPECT_EQ(1, ilogb(2)); + EXPECT_EQ(2, ilogb(4)); + EXPECT_EQ(63, ilogb(1e19)); +} diff --git a/test/libc/tinymath/logb_test.c b/test/libc/tinymath/logb_test.c index 56d6e0be..0a6c54e1 100644 --- a/test/libc/tinymath/logb_test.c +++ b/test/libc/tinymath/logb_test.c @@ -19,7 +19,6 @@ #include "libc/limits.h" #include "libc/math.h" #include "libc/testlib/testlib.h" -#include "libc/tinymath/tinymath.h" TEST(ilogb, yolo) { EXPECT_EQ(0, ilogb(1)); diff --git a/libc/runtime/spawn.S b/test/libc/tinymath/pow10_test.c similarity index 64% rename from libc/runtime/spawn.S rename to test/libc/tinymath/pow10_test.c index 883c799f..b82715d7 100644 --- a/libc/runtime/spawn.S +++ b/test/libc/tinymath/pow10_test.c @@ -1,5 +1,5 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +/*-*- 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 2020 Justine Alexandra Roberts Tunney │ │ │ @@ -16,40 +16,23 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/dce.h" -#include "libc/sysv/consts/prot.h" -#include "libc/macros.h" +#include "libc/math.h" +#include "libc/testlib/testlib.h" -/ Self-bootstraps process upon existence before calling main. -/ -/ @param r12 is argc -/ @param r13 is argv -/ @param r14 is environ -/ @param r15 is auxv -_spawn: push %rbp - mov %rsp,%rbp +TEST(pow10, testLdbl) { + EXPECT_LDBL_EQ(1, pow10l(0)); + EXPECT_LDBL_EQ(10, pow10l(1)); + EXPECT_LDBL_EQ(100, pow10l(2)); +} -/ Tune FPU settings if -ffast-math is somehow used systemically. -#ifdef __FAST_MATH__ - call __fast_math -#endif +TEST(pow10, testDouble) { + EXPECT_DOUBLE_EQ(1, pow10(0)); + EXPECT_DOUBLE_EQ(10, pow10(1)); + EXPECT_DOUBLE_EQ(100, pow10(2)); +} -/ Call decentralized initialization assembly. - call _init -#if IsModeDbg() - call _init # _init() is idempotent -#endif - -/ Call global initialization functions. - call _construct - -/ Restricts .initbss memory so it's read-only after initialization. -/ TODO: Delete this unless there's measurable performance advantage. -#if !IsTrustworthy() - mov $PROT_READ,%edi - call _piro -#endif - - pop %rbp - ret - .endfn _spawn,globl +TEST(pow10, testFloat) { + EXPECT_FLOAT_EQ(1, pow10f(0)); + EXPECT_FLOAT_EQ(10, pow10f(1)); + EXPECT_FLOAT_EQ(100, pow10f(2)); +} diff --git a/test/libc/tinymath/powl_test.c b/test/libc/tinymath/powl_test.c index ed429b37..ba2411fe 100644 --- a/test/libc/tinymath/powl_test.c +++ b/test/libc/tinymath/powl_test.c @@ -20,35 +20,31 @@ #include "libc/runtime/gc.h" #include "libc/testlib/ezbench.h" #include "libc/testlib/testlib.h" -#include "libc/tinymath/tinymath.h" #include "libc/x/x.h" TEST(powl, testLongDouble) { /* .4248496805467504836322459796959084815827285786480897 */ EXPECT_STARTSWITH(".4248496805467504", gc(xdtoa(powl(0.7, 2.4)))); - EXPECT_STARTSWITH(".4248496805467504", gc(xdtoa(tinymath_powl(0.7, 2.4)))); } TEST(powl, testDouble) { EXPECT_STARTSWITH(".4248496805467504", gc(xdtoa(pow(0.7, 2.4)))); - EXPECT_STARTSWITH(".4248496805467504", gc(xdtoa(tinymath_pow(0.7, 2.4)))); } TEST(powl, testFloat) { EXPECT_STARTSWITH(".4248496", gc(xdtoa(powf(0.7f, 2.4f)))); - EXPECT_STARTSWITH(".4248496", gc(xdtoa(tinymath_powf(0.7f, 2.4f)))); } static long double do_powl(void) { - return CONCEAL("t", tinymath_powl(CONCEAL("t", 0.7), CONCEAL("t", 0.2))); + return CONCEAL("t", powl(CONCEAL("t", 0.7), CONCEAL("t", 0.2))); } static double do_pow(void) { - return CONCEAL("x", tinymath_pow(CONCEAL("x", 0.7), CONCEAL("x", 0.2))); + return CONCEAL("x", pow(CONCEAL("x", 0.7), CONCEAL("x", 0.2))); } static float do_powf(void) { - return CONCEAL("x", tinymath_powf(CONCEAL("x", 0.7f), CONCEAL("x", 0.2f))); + return CONCEAL("x", powf(CONCEAL("x", 0.7f), CONCEAL("x", 0.2f))); } BENCH(powl, bench) { diff --git a/test/libc/tinymath/round_test.c b/test/libc/tinymath/round_test.c index 09a198cc..0771b10c 100644 --- a/test/libc/tinymath/round_test.c +++ b/test/libc/tinymath/round_test.c @@ -21,167 +21,163 @@ #include "libc/runtime/gc.h" #include "libc/str/str.h" #include "libc/testlib/testlib.h" -#include "libc/tinymath/tinymath.h" #include "libc/x/x.h" -float tinymath_roundf$k8(float); -double tinymath_round$k8(double); - FIXTURE(intrin, disableHardwareExtensions) { memset((/*unconst*/ void *)kCpuids, 0, sizeof(kCpuids)); } TEST(round, testCornerCases) { - EXPECT_STREQ("-0", gc(xdtoa(tinymath_round(-0.0)))); - EXPECT_STREQ("NAN", gc(xdtoa(tinymath_round(NAN)))); - EXPECT_STREQ("-NAN", gc(xdtoa(tinymath_round(-NAN)))); - EXPECT_STREQ("INFINITY", gc(xdtoa(tinymath_round(INFINITY)))); - EXPECT_STREQ("-INFINITY", gc(xdtoa(tinymath_round(-INFINITY)))); + EXPECT_STREQ("-0", gc(xdtoa(round(-0.0)))); + EXPECT_STREQ("NAN", gc(xdtoa(round(NAN)))); + EXPECT_STREQ("-NAN", gc(xdtoa(round(-NAN)))); + EXPECT_STREQ("INFINITY", gc(xdtoa(round(INFINITY)))); + EXPECT_STREQ("-INFINITY", gc(xdtoa(round(-INFINITY)))); } TEST(roundl, testCornerCases) { - EXPECT_STREQ("-0", gc(xdtoa(tinymath_roundl(-0.0)))); - EXPECT_STREQ("NAN", gc(xdtoa(tinymath_roundl(NAN)))); - EXPECT_STREQ("-NAN", gc(xdtoa(tinymath_roundl(-NAN)))); - EXPECT_STREQ("INFINITY", gc(xdtoa(tinymath_roundl(INFINITY)))); - EXPECT_STREQ("-INFINITY", gc(xdtoa(tinymath_roundl(-INFINITY)))); + EXPECT_STREQ("-0", gc(xdtoa(roundl(-0.0)))); + EXPECT_STREQ("NAN", gc(xdtoa(roundl(NAN)))); + EXPECT_STREQ("-NAN", gc(xdtoa(roundl(-NAN)))); + EXPECT_STREQ("INFINITY", gc(xdtoa(roundl(INFINITY)))); + EXPECT_STREQ("-INFINITY", gc(xdtoa(roundl(-INFINITY)))); } TEST(round, test) { - EXPECT_STREQ("-3", gc(xdtoa(tinymath_round(-2.5)))); - EXPECT_STREQ("-2", gc(xdtoa(tinymath_round(-1.5)))); - EXPECT_STREQ("-1", gc(xdtoa(tinymath_round(-.5)))); - EXPECT_STREQ("-0", gc(xdtoa(tinymath_round(-.4)))); - EXPECT_STREQ("0", gc(xdtoa(tinymath_round(.4)))); - EXPECT_STREQ("1", gc(xdtoa(tinymath_round(.5)))); - EXPECT_STREQ("2", gc(xdtoa(tinymath_round(1.5)))); - EXPECT_STREQ("3", gc(xdtoa(tinymath_round(2.5)))); + EXPECT_STREQ("-3", gc(xdtoa(round(-2.5)))); + EXPECT_STREQ("-2", gc(xdtoa(round(-1.5)))); + EXPECT_STREQ("-1", gc(xdtoa(round(-.5)))); + EXPECT_STREQ("-0", gc(xdtoa(round(-.4)))); + EXPECT_STREQ("0", gc(xdtoa(round(.4)))); + EXPECT_STREQ("1", gc(xdtoa(round(.5)))); + EXPECT_STREQ("2", gc(xdtoa(round(1.5)))); + EXPECT_STREQ("3", gc(xdtoa(round(2.5)))); } TEST(roundf, test) { - EXPECT_STREQ("-3", gc(xdtoa(tinymath_roundf(-2.5)))); - EXPECT_STREQ("-2", gc(xdtoa(tinymath_roundf(-1.5)))); - EXPECT_STREQ("-1", gc(xdtoa(tinymath_roundf(-.5)))); - EXPECT_STREQ("-0", gc(xdtoa(tinymath_roundf(-.4)))); - EXPECT_STREQ("0", gc(xdtoa(tinymath_roundf(.4)))); - EXPECT_STREQ("1", gc(xdtoa(tinymath_roundf(.5)))); - EXPECT_STREQ("2", gc(xdtoa(tinymath_roundf(1.5)))); - EXPECT_STREQ("3", gc(xdtoa(tinymath_roundf(2.5)))); + EXPECT_STREQ("-3", gc(xdtoa(roundf(-2.5)))); + EXPECT_STREQ("-2", gc(xdtoa(roundf(-1.5)))); + EXPECT_STREQ("-1", gc(xdtoa(roundf(-.5)))); + EXPECT_STREQ("-0", gc(xdtoa(roundf(-.4)))); + EXPECT_STREQ("0", gc(xdtoa(roundf(.4)))); + EXPECT_STREQ("1", gc(xdtoa(roundf(.5)))); + EXPECT_STREQ("2", gc(xdtoa(roundf(1.5)))); + EXPECT_STREQ("3", gc(xdtoa(roundf(2.5)))); } TEST(roundl, test) { - EXPECT_STREQ("-3", gc(xdtoa(tinymath_roundl(-2.5)))); - EXPECT_STREQ("-2", gc(xdtoa(tinymath_roundl(-1.5)))); - EXPECT_STREQ("-1", gc(xdtoa(tinymath_roundl(-.5)))); - EXPECT_STREQ("-0", gc(xdtoa(tinymath_roundl(-.4)))); - EXPECT_STREQ("0", gc(xdtoa(tinymath_roundl(.4)))); - EXPECT_STREQ("1", gc(xdtoa(tinymath_roundl(.5)))); - EXPECT_STREQ("2", gc(xdtoa(tinymath_roundl(1.5)))); - EXPECT_STREQ("3", gc(xdtoa(tinymath_roundl(2.5)))); + EXPECT_STREQ("-3", gc(xdtoa(roundl(-2.5)))); + EXPECT_STREQ("-2", gc(xdtoa(roundl(-1.5)))); + EXPECT_STREQ("-1", gc(xdtoa(roundl(-.5)))); + EXPECT_STREQ("-0", gc(xdtoa(roundl(-.4)))); + EXPECT_STREQ("0", gc(xdtoa(roundl(.4)))); + EXPECT_STREQ("1", gc(xdtoa(roundl(.5)))); + EXPECT_STREQ("2", gc(xdtoa(roundl(1.5)))); + EXPECT_STREQ("3", gc(xdtoa(roundl(2.5)))); } TEST(nearbyint, test) { - EXPECT_STREQ("-2", gc(xdtoa(tinymath_nearbyint(-2.5)))); - EXPECT_STREQ("-2", gc(xdtoa(tinymath_nearbyint(-1.5)))); - EXPECT_STREQ("-0", gc(xdtoa(tinymath_nearbyint(-.5)))); - EXPECT_STREQ("-0", gc(xdtoa(tinymath_nearbyint(-.4)))); - EXPECT_STREQ("0", gc(xdtoa(tinymath_nearbyint(.4)))); - EXPECT_STREQ("0", gc(xdtoa(tinymath_nearbyint(.5)))); - EXPECT_STREQ("2", gc(xdtoa(tinymath_nearbyint(1.5)))); - EXPECT_STREQ("2", gc(xdtoa(tinymath_nearbyint(2.5)))); + EXPECT_STREQ("-2", gc(xdtoa(nearbyint(-2.5)))); + EXPECT_STREQ("-2", gc(xdtoa(nearbyint(-1.5)))); + EXPECT_STREQ("-0", gc(xdtoa(nearbyint(-.5)))); + EXPECT_STREQ("-0", gc(xdtoa(nearbyint(-.4)))); + EXPECT_STREQ("0", gc(xdtoa(nearbyint(.4)))); + EXPECT_STREQ("0", gc(xdtoa(nearbyint(.5)))); + EXPECT_STREQ("2", gc(xdtoa(nearbyint(1.5)))); + EXPECT_STREQ("2", gc(xdtoa(nearbyint(2.5)))); } TEST(nearbyintf, test) { - EXPECT_STREQ("-2", gc(xdtoa(tinymath_nearbyintf(-2.5)))); - EXPECT_STREQ("-2", gc(xdtoa(tinymath_nearbyintf(-1.5)))); - EXPECT_STREQ("-0", gc(xdtoa(tinymath_nearbyintf(-.5)))); - EXPECT_STREQ("-0", gc(xdtoa(tinymath_nearbyintf(-.4)))); - EXPECT_STREQ("0", gc(xdtoa(tinymath_nearbyintf(.4)))); - EXPECT_STREQ("0", gc(xdtoa(tinymath_nearbyintf(.5)))); - EXPECT_STREQ("2", gc(xdtoa(tinymath_nearbyintf(1.5)))); - EXPECT_STREQ("2", gc(xdtoa(tinymath_nearbyintf(2.5)))); + EXPECT_STREQ("-2", gc(xdtoa(nearbyintf(-2.5)))); + EXPECT_STREQ("-2", gc(xdtoa(nearbyintf(-1.5)))); + EXPECT_STREQ("-0", gc(xdtoa(nearbyintf(-.5)))); + EXPECT_STREQ("-0", gc(xdtoa(nearbyintf(-.4)))); + EXPECT_STREQ("0", gc(xdtoa(nearbyintf(.4)))); + EXPECT_STREQ("0", gc(xdtoa(nearbyintf(.5)))); + EXPECT_STREQ("2", gc(xdtoa(nearbyintf(1.5)))); + EXPECT_STREQ("2", gc(xdtoa(nearbyintf(2.5)))); } TEST(nearbyintl, test) { - EXPECT_STREQ("-2", gc(xdtoa(tinymath_nearbyintl(-2.5)))); - EXPECT_STREQ("-2", gc(xdtoa(tinymath_nearbyintl(-1.5)))); - EXPECT_STREQ("-0", gc(xdtoa(tinymath_nearbyintl(-.5)))); - EXPECT_STREQ("-0", gc(xdtoa(tinymath_nearbyintl(-.4)))); - EXPECT_STREQ("0", gc(xdtoa(tinymath_nearbyintl(.4)))); - EXPECT_STREQ("0", gc(xdtoa(tinymath_nearbyintl(.5)))); - EXPECT_STREQ("2", gc(xdtoa(tinymath_nearbyintl(1.5)))); - EXPECT_STREQ("2", gc(xdtoa(tinymath_nearbyintl(2.5)))); + EXPECT_STREQ("-2", gc(xdtoa(nearbyintl(-2.5)))); + EXPECT_STREQ("-2", gc(xdtoa(nearbyintl(-1.5)))); + EXPECT_STREQ("-0", gc(xdtoa(nearbyintl(-.5)))); + EXPECT_STREQ("-0", gc(xdtoa(nearbyintl(-.4)))); + EXPECT_STREQ("0", gc(xdtoa(nearbyintl(.4)))); + EXPECT_STREQ("0", gc(xdtoa(nearbyintl(.5)))); + EXPECT_STREQ("2", gc(xdtoa(nearbyintl(1.5)))); + EXPECT_STREQ("2", gc(xdtoa(nearbyintl(2.5)))); } TEST(rint, test) { - EXPECT_STREQ("-2", gc(xdtoa(tinymath_rint(-2.5)))); - EXPECT_STREQ("-2", gc(xdtoa(tinymath_rint(-1.5)))); - EXPECT_STREQ("-0", gc(xdtoa(tinymath_rint(-.5)))); - EXPECT_STREQ("-0", gc(xdtoa(tinymath_rint(-.4)))); - EXPECT_STREQ("0", gc(xdtoa(tinymath_rint(.4)))); - EXPECT_STREQ("0", gc(xdtoa(tinymath_rint(.5)))); - EXPECT_STREQ("2", gc(xdtoa(tinymath_rint(1.5)))); - EXPECT_STREQ("2", gc(xdtoa(tinymath_rint(2.5)))); + EXPECT_STREQ("-2", gc(xdtoa(rint(-2.5)))); + EXPECT_STREQ("-2", gc(xdtoa(rint(-1.5)))); + EXPECT_STREQ("-0", gc(xdtoa(rint(-.5)))); + EXPECT_STREQ("-0", gc(xdtoa(rint(-.4)))); + EXPECT_STREQ("0", gc(xdtoa(rint(.4)))); + EXPECT_STREQ("0", gc(xdtoa(rint(.5)))); + EXPECT_STREQ("2", gc(xdtoa(rint(1.5)))); + EXPECT_STREQ("2", gc(xdtoa(rint(2.5)))); } TEST(rintf, test) { - EXPECT_STREQ("-2", gc(xdtoa(tinymath_rintf(-2.5)))); - EXPECT_STREQ("-2", gc(xdtoa(tinymath_rintf(-1.5)))); - EXPECT_STREQ("-0", gc(xdtoa(tinymath_rintf(-.5)))); - EXPECT_STREQ("-0", gc(xdtoa(tinymath_rintf(-.4)))); - EXPECT_STREQ("0", gc(xdtoa(tinymath_rintf(.4)))); - EXPECT_STREQ("0", gc(xdtoa(tinymath_rintf(.5)))); - EXPECT_STREQ("2", gc(xdtoa(tinymath_rintf(1.5)))); - EXPECT_STREQ("2", gc(xdtoa(tinymath_rintf(2.5)))); + EXPECT_STREQ("-2", gc(xdtoa(rintf(-2.5)))); + EXPECT_STREQ("-2", gc(xdtoa(rintf(-1.5)))); + EXPECT_STREQ("-0", gc(xdtoa(rintf(-.5)))); + EXPECT_STREQ("-0", gc(xdtoa(rintf(-.4)))); + EXPECT_STREQ("0", gc(xdtoa(rintf(.4)))); + EXPECT_STREQ("0", gc(xdtoa(rintf(.5)))); + EXPECT_STREQ("2", gc(xdtoa(rintf(1.5)))); + EXPECT_STREQ("2", gc(xdtoa(rintf(2.5)))); } TEST(rintl, test) { - EXPECT_STREQ("-2", gc(xdtoa(tinymath_rintl(-2.5)))); - EXPECT_STREQ("-2", gc(xdtoa(tinymath_rintl(-1.5)))); - EXPECT_STREQ("-0", gc(xdtoa(tinymath_rintl(-.5)))); - EXPECT_STREQ("-0", gc(xdtoa(tinymath_rintl(-.4)))); - EXPECT_STREQ("0", gc(xdtoa(tinymath_rintl(.4)))); - EXPECT_STREQ("0", gc(xdtoa(tinymath_rintl(.5)))); - EXPECT_STREQ("2", gc(xdtoa(tinymath_rintl(1.5)))); - EXPECT_STREQ("2", gc(xdtoa(tinymath_rintl(2.5)))); + EXPECT_STREQ("-2", gc(xdtoa(rintl(-2.5)))); + EXPECT_STREQ("-2", gc(xdtoa(rintl(-1.5)))); + EXPECT_STREQ("-0", gc(xdtoa(rintl(-.5)))); + EXPECT_STREQ("-0", gc(xdtoa(rintl(-.4)))); + EXPECT_STREQ("0", gc(xdtoa(rintl(.4)))); + EXPECT_STREQ("0", gc(xdtoa(rintl(.5)))); + EXPECT_STREQ("2", gc(xdtoa(rintl(1.5)))); + EXPECT_STREQ("2", gc(xdtoa(rintl(2.5)))); } TEST(roundf, testCornerCases) { - EXPECT_STREQ("-0", gc(xdtoa(tinymath_roundf(-0.0)))); - EXPECT_STREQ("NAN", gc(xdtoa(tinymath_roundf(NAN)))); - EXPECT_STREQ("-NAN", gc(xdtoa(tinymath_roundf(-NAN)))); - EXPECT_STREQ("INFINITY", gc(xdtoa(tinymath_roundf(INFINITY)))); - EXPECT_STREQ("-INFINITY", gc(xdtoa(tinymath_roundf(-INFINITY)))); + EXPECT_STREQ("-0", gc(xdtoa(roundf(-0.0)))); + EXPECT_STREQ("NAN", gc(xdtoa(roundf(NAN)))); + EXPECT_STREQ("-NAN", gc(xdtoa(roundf(-NAN)))); + EXPECT_STREQ("INFINITY", gc(xdtoa(roundf(INFINITY)))); + EXPECT_STREQ("-INFINITY", gc(xdtoa(roundf(-INFINITY)))); } TEST(lroundf, test) { - EXPECT_EQ(-3, tinymath_lroundf(-2.5)); - EXPECT_EQ(-2, tinymath_lroundf(-1.5)); - EXPECT_EQ(-1, tinymath_lroundf(-.5)); - EXPECT_EQ(0, tinymath_lroundf(-.0)); - EXPECT_EQ(1, tinymath_lroundf(.5)); - EXPECT_EQ(2, tinymath_lroundf(1.5)); - EXPECT_EQ(3, tinymath_lroundf(2.5)); + EXPECT_EQ(-3, lroundf(-2.5)); + EXPECT_EQ(-2, lroundf(-1.5)); + EXPECT_EQ(-1, lroundf(-.5)); + EXPECT_EQ(0, lroundf(-.0)); + EXPECT_EQ(1, lroundf(.5)); + EXPECT_EQ(2, lroundf(1.5)); + EXPECT_EQ(3, lroundf(2.5)); } TEST(lround, test) { - EXPECT_EQ(-3, tinymath_lround(-2.5)); - EXPECT_EQ(-2, tinymath_lround(-1.5)); - EXPECT_EQ(-1, tinymath_lround(-.5)); - EXPECT_EQ(-0, tinymath_lround(-.4)); - EXPECT_EQ(0, tinymath_lround(.4)); - EXPECT_EQ(1, tinymath_lround(.5)); - EXPECT_EQ(2, tinymath_lround(1.5)); - EXPECT_EQ(3, tinymath_lround(2.5)); + EXPECT_EQ(-3, lround(-2.5)); + EXPECT_EQ(-2, lround(-1.5)); + EXPECT_EQ(-1, lround(-.5)); + EXPECT_EQ(-0, lround(-.4)); + EXPECT_EQ(0, lround(.4)); + EXPECT_EQ(1, lround(.5)); + EXPECT_EQ(2, lround(1.5)); + EXPECT_EQ(3, lround(2.5)); } TEST(lroundl, test) { - EXPECT_EQ(-3, tinymath_lroundl(-2.5)); - EXPECT_EQ(-2, tinymath_lroundl(-1.5)); - EXPECT_EQ(-1, tinymath_lroundl(-.5)); - EXPECT_EQ(-0, tinymath_lroundl(-.4)); - EXPECT_EQ(0, tinymath_lroundl(.4)); - EXPECT_EQ(1, tinymath_lroundl(.5)); - EXPECT_EQ(2, tinymath_lroundl(1.5)); - EXPECT_EQ(3, tinymath_lroundl(2.5)); + EXPECT_EQ(-3, lroundl(-2.5)); + EXPECT_EQ(-2, lroundl(-1.5)); + EXPECT_EQ(-1, lroundl(-.5)); + EXPECT_EQ(-0, lroundl(-.4)); + EXPECT_EQ(0, lroundl(.4)); + EXPECT_EQ(1, lroundl(.5)); + EXPECT_EQ(2, lroundl(1.5)); + EXPECT_EQ(3, lroundl(2.5)); } diff --git a/test/libc/tinymath/test.mk b/test/libc/tinymath/test.mk index 9ed495ad..fbe434b1 100644 --- a/test/libc/tinymath/test.mk +++ b/test/libc/tinymath/test.mk @@ -50,8 +50,8 @@ o/$(MODE)/test/libc/tinymath/%.com.dbg: \ @$(APELINK) $(TEST_LIBC_TINYMATH_OBJS): \ - DEFAULT_CCFLAGS += \ - -fno-builtin + DEFAULT_CCFLAGS += \ + -fno-builtin .PHONY: o/$(MODE)/test/libc/tinymath o/$(MODE)/test/libc/tinymath: \ diff --git a/test/net/http/test.mk b/test/net/http/test.mk index cef81426..8b69c523 100644 --- a/test/net/http/test.mk +++ b/test/net/http/test.mk @@ -38,10 +38,6 @@ o/$(MODE)/test/net/http/%.com.dbg: \ $(APE) @$(APELINK) -# $(TEST_NET_HTTP_OBJS): \ -# OVERRIDE_CFLAGS += \ -# -fsanitize=address - .PHONY: o/$(MODE)/test/net/http o/$(MODE)/test/net/http: \ $(TEST_NET_HTTP_BINS) \ diff --git a/test/tool/viz/lib/bilinearscale_test.c b/test/tool/viz/lib/bilinearscale_test.c index 15cbc1fb..1fa2f1d0 100644 --- a/test/tool/viz/lib/bilinearscale_test.c +++ b/test/tool/viz/lib/bilinearscale_test.c @@ -17,9 +17,11 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/log/log.h" +#include "libc/mem/mem.h" #include "libc/rand/rand.h" #include "libc/testlib/ezbench.h" #include "libc/testlib/testlib.h" +#include "libc/x/x.h" #include "tool/viz/lib/bilinearscale.h" #include "tool/viz/lib/graphic.h" @@ -27,18 +29,18 @@ TEST(BilinearScale, testWindmill_1x1_to_2x2) { EXPECT_BINEQ( u"λλ" u"λλ", - BilinearScale(1, 2, 2, tgc(tmalloc(1 * 2 * 2)), 1, 1, 1, - tgc(tunbing(u"λ")), 0, 1, 2, 2, 1, 1, .5, .5, 0, 0)); + BilinearScale(1, 2, 2, gc(malloc(1 * 2 * 2)), 1, 1, 1, gc(xunbing(u"λ")), + 0, 1, 2, 2, 1, 1, .5, .5, 0, 0)); } TEST(BilinearScale, testWindmill_4x4_to_2x2) { EXPECT_BINEQ(u"λ " u" λ", - BilinearScale(1, 2, 2, tgc(tmalloc(2 * 2)), 1, 4, 4, - tgc(tunbing(u"λλ  " - u"λλ  " - u"  λλ" - u"  λλ")), + BilinearScale(1, 2, 2, gc(malloc(2 * 2)), 1, 4, 4, + gc(xunbing(u"λλ  " + u"λλ  " + u"  λλ" + u"  λλ")), 0, 1, 2, 2, 4, 4, 2, 2, 0, 0)); } @@ -47,15 +49,15 @@ TEST(BilinearScale, testWindmill_8x8_to_4x4) { u"λλ  " u"  λλ" u"  λλ", - BilinearScale(1, 4, 4, tgc(tmalloc(4 * 4)), 1, 8, 8, - tgc(tunbing(u"λλλλ    " - u"λλλλ    " - u"λλλλ    " - u"λλλλ    " - u"    λλλλ" - u"    λλλλ" - u"    λλλλ" - u"    λλλλ")), + BilinearScale(1, 4, 4, gc(malloc(4 * 4)), 1, 8, 8, + gc(xunbing(u"λλλλ    " + u"λλλλ    " + u"λλλλ    " + u"λλλλ    " + u"    λλλλ" + u"    λλλλ" + u"    λλλλ" + u"    λλλλ")), 0, 1, 4, 4, 8, 8, 2, 2, 0, 0)); } @@ -68,11 +70,11 @@ TEST(BilinearScale, testWindmill_4x4_to_8x8) { u"    ⁇λλλ" u"    ⁇λλλ" u"    ⁇λλλ", - BilinearScale(1, 8, 8, tgc(tmalloc(8 * 8)), 1, 4, 4, - tgc(tunbing(u"λλ  " - u"λλ  " - u"  λλ" - u"  λλ")), + BilinearScale(1, 8, 8, gc(malloc(8 * 8)), 1, 4, 4, + gc(xunbing(u"λλ  " + u"λλ  " + u"  λλ" + u"  λλ")), 0, 1, 8, 8, 4, 4, .5, .5, 0, 0)); } @@ -85,12 +87,12 @@ TEST(BilinearScale, testWindmill_5x5_to_8x8_withRatioIntent) { u"     λλλ" u"     λλλ" u"     λλλ", - BilinearScale(1, 8, 8, tgc(tmalloc(8 * 8)), 1, 5, 5, - tgc(tunbing(u"λλλ  " - u"λλλ  " - u"  λλλ" - u"   λλ" - u"   λλ")), + BilinearScale(1, 8, 8, gc(malloc(8 * 8)), 1, 5, 5, + gc(xunbing(u"λλλ  " + u"λλλ  " + u"  λλλ" + u"   λλ" + u"   λλ")), 0, 1, 8, 8, 5, 5, 2 / 3., 2 / 3., 0, 0)); } @@ -103,12 +105,12 @@ TEST(BilinearScale, testWindmill_5x5_to_8x8_withoutRatioIntent) { u"   →Å└λλ" u"     oλλ" u"     oλλ", - BilinearScale(1, 8, 8, tgc(tmalloc(8 * 8)), 1, 5, 5, - tgc(tunbing(u"λλλ  " - u"λλλ  " - u"  λλλ" - u"   λλ" - u"   λλ")), + BilinearScale(1, 8, 8, gc(malloc(8 * 8)), 1, 5, 5, + gc(xunbing(u"λλλ  " + u"λλλ  " + u"  λλλ" + u"   λλ" + u"   λλ")), 0, 1, 8, 8, 5, 5, 5 / 8., 5 / 8., 0, 0)); } @@ -117,15 +119,15 @@ TEST(BilinearScale, testNyquistTorture) { u"████" u" ███" u"███ ", - BilinearScale(1, 4, 4, tgc(tmalloc(4 * 4)), 1, 8, 8, - tgc(tunbing(u"█ █ █ " - u" █ █ █ " - u"█ █ █ █ " - u" █ █ █ █" - u" █ █ █ " - u" █ █ █ " - u"█ █ █ " - u" █ █ ")), + BilinearScale(1, 4, 4, gc(malloc(4 * 4)), 1, 8, 8, + gc(xunbing(u"█ █ █ " + u" █ █ █ " + u"█ █ █ █ " + u" █ █ █ █" + u" █ █ █ " + u" █ █ █ " + u"█ █ █ " + u" █ █ ")), 0, 1, 4, 4, 8, 8, 2, 2, 0, 0)); } @@ -137,8 +139,8 @@ BENCH(BilinearScale, Bench) { h1 = 1080; w2 = 1136; h2 = 136; - src = tgc(tmemalign(32, w1 * h1 * c)); - dst = tgc(tmemalign(32, w2 * h2 * c)); + src = gc(memalign(32, w1 * h1 * c)); + dst = gc(memalign(32, w2 * h2 * c)); EZBENCH2("BilinearScale", donothing, BilinearScale(c, h2, w2, dst, c, h1, w1, src, 0, c, h2, w2, h1, w1, h2 / h1, w2 / w1, 0, 0)); diff --git a/test/tool/viz/lib/halfblit_test.c b/test/tool/viz/lib/halfblit_test.c index bae939a4..1f21b89a 100644 --- a/test/tool/viz/lib/halfblit_test.c +++ b/test/tool/viz/lib/halfblit_test.c @@ -16,16 +16,19 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/fmt/bing.internal.h" +#include "libc/runtime/gc.h" #include "libc/testlib/testlib.h" +#include "libc/x/x.h" #include "tool/viz/lib/halfblit.h" TEST(halfblit, test_4x4_to_2x2) { EXPECT_BINEQ(u" ☺" u"►◄", - halfblit(2, tgc(tunbing(u" ☺☻♥" - u"►◄↕‼" - u"♀♪♫☼" - u"∟↔▲▼")))); + halfblit(2, gc(xunbing(u" ☺☻♥" + u"►◄↕‼" + u"♀♪♫☼" + u"∟↔▲▼")))); } TEST(halfblit, test_8x8_to_4x4) { @@ -33,12 +36,12 @@ TEST(halfblit, test_8x8_to_4x4) { u"►◄↕‼" u"◘○◙♂" u"↑↓→←", - halfblit(4, tgc(tunbing(u" ☺☻♥♦♣♠•" - u"►◄↕‼¶§▬↨" - u"◘○◙♂♀♪♫☼" - u"↑↓→←∟↔▲▼" - u"01234567" - u"░▒▓│┤╡╢╖" - u"╕╣║╗╝╜╛┐" - u"89:;<=>?")))); + halfblit(4, gc(xunbing(u" ☺☻♥♦♣♠•" + u"►◄↕‼¶§▬↨" + u"◘○◙♂♀♪♫☼" + u"↑↓→←∟↔▲▼" + u"01234567" + u"░▒▓│┤╡╢╖" + u"╕╣║╗╝╜╛┐" + u"89:;<=>?")))); } diff --git a/third_party/chibicc/as.c b/third_party/chibicc/as.c index fd720e0f..c154db24 100644 --- a/third_party/chibicc/as.c +++ b/third_party/chibicc/as.c @@ -522,6 +522,7 @@ static int AppendSection(struct As *a, int name, int flags, int type) { int i; APPEND(a->sections); i = a->sections.n - 1; + CHECK_LT(i, SHN_LORESERVE); a->sections.p[i].name = name; a->sections.p[i].flags = flags; a->sections.p[i].type = type; @@ -1805,6 +1806,15 @@ static void OnSize(struct As *a, struct Slice s) { a->symbols.p[i].size = GetInt(a); } +static void OnComm(struct As *a, struct Slice s) { + int i; + i = GetSymbol(a, a->things.p[a->i++].i); + ConsumeComma(a); + a->symbols.p[i].size = GetInt(a); + a->symbols.p[i].type = STT_COMMON; + a->symbols.p[i].section = SHN_COMMON; +} + static void OpVisibility(struct As *a, int visibility) { int i; for (;;) { @@ -3118,6 +3128,7 @@ static const struct Directive8 { {".balign", OnAlign}, // {".bss", OnBss}, // {".byte", OnByte}, // + {".comm", OnComm}, // {".data", OnData}, // {".double", OnDouble}, // {".err", OnErr}, // @@ -3280,8 +3291,8 @@ static const struct Directive8 { {"fildll", OnFildll}, // {"fildq", OnFildq}, // {"filds", OnFilds}, // - {"fistpq", OnFistpq}, // {"fistpll", OnFistpq}, // + {"fistpq", OnFistpq}, // {"fisttpll", OnFisttpq}, // {"fisttpq", OnFisttpq}, // {"fisttps", OnFisttps}, // @@ -3906,6 +3917,9 @@ static void Objectify(struct As *a, int path) { a->symbols.p[i].ref = elfwriter_appendsym( elf, p, ELF64_ST_INFO(a->symbols.p[i].stb, a->symbols.p[i].type), a->symbols.p[i].stv, a->symbols.p[i].offset, a->symbols.p[i].size); + if (a->symbols.p[i].section >= SHN_LORESERVE) { + elfwriter_setsection(elf, a->symbols.p[i].ref, a->symbols.p[i].section); + } free(p); } for (i = 0; i < a->sections.n; ++i) { diff --git a/third_party/chibicc/test/test.mk b/third_party/chibicc/test/test.mk index 6c2add98..35c916dd 100644 --- a/third_party/chibicc/test/test.mk +++ b/third_party/chibicc/test/test.mk @@ -21,8 +21,13 @@ THIRD_PARTY_CHIBICC_TEST_HDRS = $(filter %.h,$(THIRD_PARTY_CHIBICC_TEST_FILES)) THIRD_PARTY_CHIBICC_TEST_TESTS = $(THIRD_PARTY_CHIBICC_TEST_COMS:%=%.ok) THIRD_PARTY_CHIBICC_TEST_COMS = \ - $(THIRD_PARTY_CHIBICC_TEST_SRCS_TEST:%.c=o/$(MODE)/%.com) \ + $(THIRD_PARTY_CHIBICC_TEST_SRCS_TEST:%.c=o/$(MODE)/%.com) + +# TODO(jart): make chibicc compiled chibicc work with asan runtime +ifneq ($(MODE),dbg) +THIRD_PARTY_CHIBICC_TEST_COMS += \ $(THIRD_PARTY_CHIBICC_TEST_SRCS_TEST:%.c=o/$(MODE)/%2.com) +endif THIRD_PARTY_CHIBICC_TEST_OBJS = \ $(THIRD_PARTY_CHIBICC_TEST_SRCS:%.c=o/$(MODE)/%.chibicc.o) diff --git a/third_party/dlmalloc/dlmalloc-usable.c b/third_party/dlmalloc/dlmalloc-usable.c deleted file mode 100644 index 8ee9b31f..00000000 --- a/third_party/dlmalloc/dlmalloc-usable.c +++ /dev/null @@ -1,10 +0,0 @@ -#include "libc/mem/mem.h" -#include "third_party/dlmalloc/dlmalloc.internal.h" - -size_t dlmalloc_usable_size(const void* mem) { - if (mem != 0) { - mchunkptr p = mem2chunk(mem); - if (is_inuse(p)) return chunksize(p) - overhead_for(p); - } - return 0; -} diff --git a/third_party/dlmalloc/dlmalloc.c b/third_party/dlmalloc/dlmalloc.c index a0bc5200..4e02470d 100644 --- a/third_party/dlmalloc/dlmalloc.c +++ b/third_party/dlmalloc/dlmalloc.c @@ -1,9 +1,11 @@ #include "libc/bits/initializer.internal.h" #include "libc/bits/safemacros.h" +#include "libc/bits/weaken.h" #include "libc/calls/internal.h" #include "libc/calls/struct/sysinfo.h" #include "libc/dce.h" #include "libc/fmt/conv.h" +#include "libc/intrin/asan.internal.h" #include "libc/limits.h" #include "libc/macros.h" #include "libc/mem/mem.h" @@ -34,20 +36,12 @@ hidden struct MallocParams g_mparams; * Note that contiguous allocations are what Doug Lea recommends. */ static void *dlmalloc_requires_more_vespene_gas(size_t size) { - if (0) { - size_t need = mallinfo().arena + size; - if (need > 8 * 1024 * 1024) { - struct sysinfo info; - if (sysinfo(&info) != -1) { - if (info.freeram < (info.totalram >> 1) && - need > info.totalram * info.mem_unit / 2) { - write(STDERR_FILENO, OOM_WARNING, strlen(OOM_WARNING)); - return NULL; - } - } - } + char *p; + p = mapanon(size); + if (weaken(__asan_poison)) { + weaken(__asan_poison)((uintptr_t)p, size, kAsanHeapFree); } - return mapanon(size); + return p; } /* ─────────────────────────── mspace management ─────────────────────────── */ @@ -826,6 +820,14 @@ void dlfree(void *mem) { #endif /* FOOTERS */ } +size_t dlmalloc_usable_size(const void *mem) { + if (mem != 0) { + mchunkptr p = mem2chunk(mem); + if (is_inuse(p)) return chunksize(p) - overhead_for(p); + } + return 0; +} + textstartup void dlmalloc_init(void) { #ifdef NEED_GLOBAL_LOCK_INIT if (malloc_global_mutex_status <= 0) init_malloc_global_mutex(); @@ -868,3 +870,75 @@ textstartup void dlmalloc_init(void) { } RELEASE_MALLOC_GLOBAL_LOCK(); } + +void *dlmemalign$impl(mstate m, size_t alignment, size_t bytes) { + void *mem = 0; + if (alignment < MIN_CHUNK_SIZE) { /* must be at least a minimum chunk size */ + alignment = MIN_CHUNK_SIZE; /* is 32 bytes on NexGen32e */ + } + if ((alignment & (alignment - SIZE_T_ONE)) != 0) { /* Ensure a power of 2 */ + alignment = roundup2pow(alignment); + } + if (bytes >= MAX_REQUEST - alignment) { + if (m != 0) { /* Test isn't needed but avoids compiler warning */ + enomem(); + } + } else { + size_t nb = request2size(bytes); + size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD; + mem = dlmalloc(req); + if (mem != 0) { + mchunkptr p = mem2chunk(mem); + if (PREACTION(m)) return 0; + if ((((size_t)(mem)) & (alignment - 1)) != 0) { /* misaligned */ + /* + Find an aligned spot inside chunk. Since we need to give + back leading space in a chunk of at least MIN_CHUNK_SIZE, if + the first calculation places us at a spot with less than + MIN_CHUNK_SIZE leader, we can move to the next aligned spot. + We've allocated enough total room so that this is always + possible. + */ + char *br = (char *)mem2chunk((size_t)( + ((size_t)((char *)mem + alignment - SIZE_T_ONE)) & -alignment)); + char *pos = ((size_t)(br - (char *)(p)) >= MIN_CHUNK_SIZE) + ? br + : br + alignment; + mchunkptr newp = (mchunkptr)pos; + size_t leadsize = pos - (char *)(p); + size_t newsize = chunksize(p) - leadsize; + if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */ + newp->prev_foot = p->prev_foot + leadsize; + newp->head = newsize; + } else { /* Otherwise, give back leader, use the rest */ + set_inuse(m, newp, newsize); + set_inuse(m, p, leadsize); + dlmalloc_dispose_chunk(m, p, leadsize); + } + p = newp; + } + /* Give back spare room at the end */ + if (!is_mmapped(p)) { + size_t size = chunksize(p); + if (size > nb + MIN_CHUNK_SIZE) { + size_t remainder_size = size - nb; + mchunkptr remainder = chunk_plus_offset(p, nb); + set_inuse(m, p, nb); + set_inuse(m, remainder, remainder_size); + dlmalloc_dispose_chunk(m, remainder, remainder_size); + } + } + mem = chunk2mem(p); + assert(chunksize(p) >= nb); + assert(((size_t)mem & (alignment - 1)) == 0); + check_inuse_chunk(m, p); + POSTACTION(m); + } + } + return ADDRESS_BIRTH_ACTION(mem); +} + +void *dlmemalign(size_t alignment, size_t bytes) { + if (alignment <= MALLOC_ALIGNMENT) return dlmalloc(bytes); + return dlmemalign$impl(g_dlmalloc, alignment, bytes); +} diff --git a/third_party/dlmalloc/dlmemalign-impl.c b/third_party/dlmalloc/dlmemalign-impl.c deleted file mode 100644 index a1725bf3..00000000 --- a/third_party/dlmalloc/dlmemalign-impl.c +++ /dev/null @@ -1,70 +0,0 @@ -#include "libc/bits/bits.h" -#include "libc/mem/mem.h" -#include "libc/sysv/errfuns.h" -#include "third_party/dlmalloc/dlmalloc.internal.h" - -void* dlmemalign$impl(mstate m, size_t alignment, size_t bytes) { - void* mem = 0; - if (alignment < MIN_CHUNK_SIZE) { /* must be at least a minimum chunk size */ - alignment = MIN_CHUNK_SIZE; /* is 32 bytes on NexGen32e */ - } - if ((alignment & (alignment - SIZE_T_ONE)) != 0) { /* Ensure a power of 2 */ - alignment = roundup2pow(alignment); - } - if (bytes >= MAX_REQUEST - alignment) { - if (m != 0) { /* Test isn't needed but avoids compiler warning */ - enomem(); - } - } else { - size_t nb = request2size(bytes); - size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD; - mem = dlmalloc(req); - if (mem != 0) { - mchunkptr p = mem2chunk(mem); - if (PREACTION(m)) return 0; - if ((((size_t)(mem)) & (alignment - 1)) != 0) { /* misaligned */ - /* - Find an aligned spot inside chunk. Since we need to give - back leading space in a chunk of at least MIN_CHUNK_SIZE, if - the first calculation places us at a spot with less than - MIN_CHUNK_SIZE leader, we can move to the next aligned spot. - We've allocated enough total room so that this is always - possible. - */ - char* br = (char*)mem2chunk((size_t)( - ((size_t)((char*)mem + alignment - SIZE_T_ONE)) & -alignment)); - char* pos = - ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE) ? br : br + alignment; - mchunkptr newp = (mchunkptr)pos; - size_t leadsize = pos - (char*)(p); - size_t newsize = chunksize(p) - leadsize; - if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */ - newp->prev_foot = p->prev_foot + leadsize; - newp->head = newsize; - } else { /* Otherwise, give back leader, use the rest */ - set_inuse(m, newp, newsize); - set_inuse(m, p, leadsize); - dlmalloc_dispose_chunk(m, p, leadsize); - } - p = newp; - } - /* Give back spare room at the end */ - if (!is_mmapped(p)) { - size_t size = chunksize(p); - if (size > nb + MIN_CHUNK_SIZE) { - size_t remainder_size = size - nb; - mchunkptr remainder = chunk_plus_offset(p, nb); - set_inuse(m, p, nb); - set_inuse(m, remainder, remainder_size); - dlmalloc_dispose_chunk(m, remainder, remainder_size); - } - } - mem = chunk2mem(p); - assert(chunksize(p) >= nb); - assert(((size_t)mem & (alignment - 1)) == 0); - check_inuse_chunk(m, p); - POSTACTION(m); - } - } - return ADDRESS_BIRTH_ACTION(mem); -} diff --git a/third_party/dlmalloc/dlmemalign.c b/third_party/dlmalloc/dlmemalign.c deleted file mode 100644 index 26b679c5..00000000 --- a/third_party/dlmalloc/dlmemalign.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "libc/mem/mem.h" -#include "third_party/dlmalloc/dlmalloc.internal.h" - -void *dlmemalign(size_t alignment, size_t bytes) { - if (alignment <= MALLOC_ALIGNMENT) return dlmalloc(bytes); - return dlmemalign$impl(g_dlmalloc, alignment, bytes); -} diff --git a/third_party/stb/stb.mk b/third_party/stb/stb.mk index 55ff9c13..75770301 100644 --- a/third_party/stb/stb.mk +++ b/third_party/stb/stb.mk @@ -62,12 +62,6 @@ $(THIRD_PARTY_STB_A_OBJS): \ -ffunction-sections \ -fdata-sections -# o//third_party/stb/stb_image_write.o \ -# o//third_party/stb/stb_image.o: \ -# OVERRIDE_CFLAGS += \ -# -ftrapv \ -# -fsanitize=address - $(THIRD_PARTY_STB_A_OBJS): \ OVERRIDE_CPPFLAGS += \ -DSTACK_FRAME_UNLIMITED diff --git a/third_party/third_party.mk b/third_party/third_party.mk index 63217935..db1822be 100644 --- a/third_party/third_party.mk +++ b/third_party/third_party.mk @@ -1,10 +1,15 @@ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ #───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ +# TODO(jart): make chibicc compiled chibicc work with asan runtime +ifneq ($(MODE),dbg) +THIRD_PARTY_CHIBICC_XXX = o/$(MODE)/third_party/chibicc +endif + .PHONY: o/$(MODE)/third_party o/$(MODE)/third_party: \ o/$(MODE)/third_party/blas \ - o/$(MODE)/third_party/chibicc \ + $(THIRD_PARTY_CHIBICC_XXX) \ o/$(MODE)/third_party/compiler_rt \ o/$(MODE)/third_party/dlmalloc \ o/$(MODE)/third_party/gdtoa \ diff --git a/third_party/zlib/zlib.mk b/third_party/zlib/zlib.mk index c363f74d..b44e44f7 100644 --- a/third_party/zlib/zlib.mk +++ b/third_party/zlib/zlib.mk @@ -27,6 +27,7 @@ THIRD_PARTY_ZLIB_A_CHECKS = \ THIRD_PARTY_ZLIB_A_DIRECTDEPS = \ LIBC_INTRIN \ LIBC_NEXGEN32E \ + LIBC_STR \ LIBC_STUBS THIRD_PARTY_ZLIB_A_DEPS := \ diff --git a/tool/build/blinkenlights.c b/tool/build/blinkenlights.c index c79df3e7..0d47a85c 100644 --- a/tool/build/blinkenlights.c +++ b/tool/build/blinkenlights.c @@ -34,6 +34,7 @@ #include "libc/fmt/conv.h" #include "libc/fmt/fmt.h" #include "libc/fmt/itoa.h" +#include "libc/intrin/asan.internal.h" #include "libc/intrin/pcmpeqb.h" #include "libc/intrin/pmovmskb.h" #include "libc/log/check.h" @@ -441,6 +442,25 @@ static int VirtualBing(int64_t v) { return rc; } +static int VirtualShadow(int64_t v) { + int rc; + char *p; + jmp_buf busted; + if (0x7fff8000 <= v && v < 0x100080000000) return -2; + onbusted = busted; + if ((p = FindReal(m, (v >> 3) + 0x7fff8000))) { + if (!setjmp(busted)) { + rc = p[0] & 0xff; + } else { + rc = -1; + } + } else { + rc = -1; + } + onbusted = NULL; + return rc; +} + static void ScrollOp(struct Panel *p, long op) { long n; opline = op; @@ -1260,7 +1280,8 @@ static void DrawMemoryZoomed(struct Panel *p, struct MemoryView *view, static void DrawMemoryUnzoomed(struct Panel *p, struct MemoryView *view, long histart, long hiend) { - long i, j, k, c; + long i, j, k; + int c, s, x, sc; bool high, changed; high = false; for (i = 0; i < p->bottom - p->top; ++i) { @@ -1268,6 +1289,35 @@ static void DrawMemoryUnzoomed(struct Panel *p, struct MemoryView *view, for (j = 0; j < DUMPWIDTH; ++j) { k = (view->start + i) * DUMPWIDTH + j; c = VirtualBing(k); + s = VirtualShadow(k); + if (s != -1) { + if (s == -2) { + /* grey for shadow memory */ + x = 235; + } else { + sc = (signed char)s; + if (sc > 7) { + x = 129; /* PURPLE: shadow corruption */ + } else if (sc == kAsanHeapFree) { + x = 17; /* NAVYBLUE: heap freed */ + } else if (sc == kAsanRelocated) { + x = 18; /* DARKBLUE: heap relocated */ + } else if (sc == kAsanHeapUnderrun || sc == kAsanAllocaUnderrun) { + x = 53; /* RED+PURPLETINGE: heap underrun */ + } else if (sc == kAsanHeapOverrun || sc == kAsanAllocaOverrun) { + x = 52; /* RED: heap overrun */ + } else if (sc < 0) { + x = 52; /* RED: uncategorized invalid */ + } else if (sc > 0 && (k & 7) >= sc) { + x = 54; /* REDPURP: invalid address (skew) */ + } else if (!sc || (sc > 0 && (k & 7) < sc)) { + x = 22; /* GREEN: valid address */ + } else { + abort(); + } + } + AppendFmt(&p->lines[i], "\e[38;5;253;48;5;%dm", x); + } changed = histart <= k && k < hiend; if (changed && !high) { high = true; @@ -1277,6 +1327,9 @@ static void DrawMemoryUnzoomed(struct Panel *p, struct MemoryView *view, high = false; } AppendWide(&p->lines[i], c); + if (s != -1) { + AppendStr(&p->lines[i], "\e[39;49m"); + } } if (high) { AppendStr(&p->lines[i], "\e[27m"); diff --git a/tool/build/calculator.c b/tool/build/calculator.c index 8220803c..2a314ece 100644 --- a/tool/build/calculator.c +++ b/tool/build/calculator.c @@ -671,7 +671,7 @@ void CleanupTerminal(void) { } void StartInteractive(void) { - if (!interactive && !isterminalinarticulate() && isatty(fileno(stdin)) && + if (!interactive && !IsTerminalInarticulate() && isatty(fileno(stdin)) && isatty(fileno(stdout)) && cancolor()) { interactive = true; } diff --git a/tool/build/emubin/emubin.mk b/tool/build/emubin/emubin.mk index 6c134c6c..354c36f3 100644 --- a/tool/build/emubin/emubin.mk +++ b/tool/build/emubin/emubin.mk @@ -68,6 +68,10 @@ o/tiny/tool/build/emubin/mdatest.bin.dbg: \ o/tiny/tool/build/emubin/mdatest.real.o @$(ELFLINK) -z max-page-size=0x10 -T tool/build/emucrt/real.lds +$(TOOL_BUILD_EMUBIN_OBJS): \ + OVERRIDE_CFLAGS += \ + $(NO_MAGIC) + .PHONY: o/$(MODE)/tool/build/emubin o/$(MODE)/tool/build/emubin: \ $(TOOL_BUILD_EMUBIN_BINS) \ diff --git a/tool/build/lib/buildlib.mk b/tool/build/lib/buildlib.mk index ed162c7a..97128341 100644 --- a/tool/build/lib/buildlib.mk +++ b/tool/build/lib/buildlib.mk @@ -61,12 +61,6 @@ $(TOOL_BUILD_LIB_A).pkg: \ $(TOOL_BUILD_LIB_A_OBJS) \ $(foreach x,$(TOOL_BUILD_LIB_A_DIRECTDEPS),$($(x)_A).pkg) -# ifeq (,$(MODE)) -# $(TOOL_BUILD_LIB_A_OBJS): \ -# OVERRIDE_CFLAGS += \ -# -fsanitize=address -# endif - o/$(MODE)/tool/build/lib/ssefloat.o: \ TARGET_ARCH += \ -msse3 diff --git a/tool/build/lib/machine.c b/tool/build/lib/machine.c index 9c24abac..aa223d19 100644 --- a/tool/build/lib/machine.c +++ b/tool/build/lib/machine.c @@ -449,6 +449,7 @@ static void OpCmpxchg16b(struct Machine *m, uint32_t rde) { static void OpRdrand(struct Machine *m, uint32_t rde) { WriteRegister(rde, RegRexbRm(m, rde), rand64()); + m->flags = SetFlag(m->flags, FLAGS_CF, true); } static void OpRdseed(struct Machine *m, uint32_t rde) { diff --git a/tool/emacs/cosmo-c-keywords.el b/tool/emacs/cosmo-c-keywords.el index 9428ba61..1af8f1ca 100644 --- a/tool/emacs/cosmo-c-keywords.el +++ b/tool/emacs/cosmo-c-keywords.el @@ -169,6 +169,7 @@ "nodebuginfo" "frownedupon" "wontreturn" + "noasan" "initarray" "mayalias" "noinstrument" diff --git a/tool/emacs/cosmo-cpp-constants.el b/tool/emacs/cosmo-cpp-constants.el index d317d0f0..274d1be7 100644 --- a/tool/emacs/cosmo-cpp-constants.el +++ b/tool/emacs/cosmo-cpp-constants.el @@ -152,6 +152,7 @@ "__PG__" "__MFENTRY__" "__MNO_VZEROUPPER__" + "__FSANITIZE_ADDRESS__" "__FSANITIZE_UNDEFINED__" "__MNOP_MCOUNT__" "__MRECORD_MCOUNT__")) diff --git a/tool/emacs/cosmo-stuff.el b/tool/emacs/cosmo-stuff.el index 6601622f..2c8fbbf4 100644 --- a/tool/emacs/cosmo-stuff.el +++ b/tool/emacs/cosmo-stuff.el @@ -440,8 +440,8 @@ ;; -ffast-math -funsafe-math-optimizations -fsched2-use-superblocks -fjump-tables (cond ((not (eq 0 (logand 8 arg))) (cosmo--assembly (setq arg (logand (lognot 8))) - "SILENT=0 COPTS='-Os'")) - (t (cosmo--assembly arg "SILENT=0 COPTS='-Os' TARGET_ARCH='-mdispatch-scheduler' CPPFLAGS='-DSTACK_FRAME_UNLIMITED'")))) + "SILENT=0 OVERRIDE_COPTS='-fverbose-asm -fsanitize=address'")) + (t (cosmo--assembly arg "SILENT=0 OVERRIDE_COPTS='-fverbose-asm -fsanitize=address' CPPFLAGS='-DSTACK_FRAME_UNLIMITED'")))) (defun cosmo-assembly-native (arg) (interactive "P") diff --git a/tool/net/net.mk b/tool/net/net.mk index 8d18ed90..93202dee 100644 --- a/tool/net/net.mk +++ b/tool/net/net.mk @@ -27,7 +27,6 @@ TOOL_NET_DIRECTDEPS = \ LIBC_FMT \ LIBC_INTRIN \ LIBC_LOG \ - LIBC_LOG_ASAN \ LIBC_MEM \ LIBC_NEXGEN32E \ LIBC_RAND \ @@ -85,12 +84,6 @@ o/$(MODE)/tool/net/greenbean.com.dbg: \ $(APE) @$(APELINK) -# ifeq (,$(MODE)) -# $(TOOL_NET_OBJS): \ -# OVERRIDE_CFLAGS += \ -# -fsanitize=address -# endif - .PHONY: o/$(MODE)/tool/net o/$(MODE)/tool/net: \ $(TOOL_NET_BINS) \ diff --git a/tool/viz/lib/vizlib.mk b/tool/viz/lib/vizlib.mk index 0c6a1cc7..3f7d1cca 100644 --- a/tool/viz/lib/vizlib.mk +++ b/tool/viz/lib/vizlib.mk @@ -89,12 +89,6 @@ $(TOOL_VIZ_LIB_A).pkg: \ $(TOOL_VIZ_LIB_A_OBJS) \ $(foreach x,$(TOOL_VIZ_LIB_A_DIRECTDEPS),$($(x)_A).pkg) -# ifeq (,$(MODE)) -# $(TOOL_VIZ_LIB_A_OBJS): \ -# OVERRIDE_CFLAGS += \ -# -fsanitize=address -# endif - $(TOOL_VIZ_LIB_A_OBJS): tool/viz/lib/vizlib.mk TOOL_VIZ_LIB_LIBS = $(foreach x,$(TOOL_VIZ_LIB_ARTIFACTS),$($(x))) diff --git a/tool/viz/printvideo.c b/tool/viz/printvideo.c index 9fb6b623..51ce661e 100644 --- a/tool/viz/printvideo.c +++ b/tool/viz/printvideo.c @@ -1467,7 +1467,7 @@ int main(int argc, char *argv[]) { sigaddset(&wut, SIGCHLD); sigaddset(&wut, SIGPIPE); sigprocmask(SIG_SETMASK, &wut, NULL); - if (!NoDebug()) showcrashreports(); + showcrashreports(); fullclear_ = true; GetOpts(argc, argv); if (!tuned_) PickDefaults(); diff --git a/tool/viz/viz.mk b/tool/viz/viz.mk index 2a9d194a..811000a7 100644 --- a/tool/viz/viz.mk +++ b/tool/viz/viz.mk @@ -84,12 +84,6 @@ $(TOOL_VIZ_OBJS): \ $(BUILD_FILES) \ tool/viz/viz.mk -# ifeq (,$(MODE)) -# $(TOOL_VIZ_OBJS): \ -# OVERRIDE_CFLAGS += \ -# -fsanitize=address -# endif - .PHONY: o/$(MODE)/tool/viz o/$(MODE)/tool/viz: \ o/$(MODE)/tool/viz/lib \ diff --git a/tool/viz/xterm256gradient.c b/tool/viz/xterm256gradient.c new file mode 100644 index 00000000..089e77cf --- /dev/null +++ b/tool/viz/xterm256gradient.c @@ -0,0 +1,77 @@ +/*-*- 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 2021 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/math.h" +#include "libc/stdio/stdio.h" + +#define N 8 + +#define SQR(X) ((X) * (X)) + +static const uint8_t kXtermCube[6] = {0, 0137, 0207, 0257, 0327, 0377}; + +static int rgb2xterm256(int r, int g, int b) { + int cerr, gerr, ir, ig, ib, gray, grai, cr, cg, cb, gv; + gray = round(r * .299 + g * .587 + b * .114); + grai = gray > 238 ? 23 : (gray - 3) / 10; + ir = r < 48 ? 0 : r < 115 ? 1 : (r - 35) / 40; + ig = g < 48 ? 0 : g < 115 ? 1 : (g - 35) / 40; + ib = b < 48 ? 0 : b < 115 ? 1 : (b - 35) / 40; + cr = kXtermCube[ir]; + cg = kXtermCube[ig]; + cb = kXtermCube[ib]; + gv = 8 + 10 * grai; + cerr = SQR(cr - r) + SQR(cg - g) + SQR(cb - b); + gerr = SQR(gv - r) + SQR(gv - g) + SQR(gv - b); + if (cerr <= gerr) { + return 16 + 36 * ir + 6 * ig + ib; + } else { + return 232 + grai; + } +} + +int main(int argc, char *argv[]) { + double d; + int i, j, x; + int r, g, b; + double G[N][3]; + double rgb[2][3] = { + {1, 0, 0}, + {0, 1, 0}, + }; + + for (i = 0; i < N; ++i) { + for (j = 0; j < 3; ++j) { + d = (rgb[1][j] - rgb[0][j]) / (N - 1); + G[i][j] = rgb[0][j] + d * i; + } + } + + for (i = 0; i < N; ++i) { + r = round(G[i][0] * 255); + g = round(G[i][1] * 255); + b = round(G[i][2] * 255); + x = rgb2xterm256(r, g, b); + printf("\e[38;5;232;48;5;%dmabcdefg \e[0m %3d " + "\e[38;5;232;48;2;%d;%d;%dmabcdgefg \e[0m " + "%3d %3d %3d %f %f %f\n", + x, x, r, g, b, r, g, b, G[i][0], G[i][1], G[i][2]); + } + + return 0; +}