diff --git a/ape/lib/apelib.mk b/ape/lib/apelib.mk index 2b38a38e7..f7cf68669 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 197518fc2..bfef27189 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 07c7446b8..ea6e01e2f 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 4359b9c29..c135e0bdc 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 b6919ca4b..e1d83bf15 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 7f06a5888..d4e130f36 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 638be2c60..b5dfa8950 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 06b6f65ad..330979712 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 b659cbe5c..c4c6ab152 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 2c8372142..9cf38a379 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 58d4554ed..3b96bb137 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 0ebbf1b99..4f95461e6 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 53ad1b0cc..a16f076bb 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 cfd227f08..920414084 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 000000000..c95cd61eb --- /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 238be618d..5801ec599 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 7c0c89dd9..195d5acf9 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 1e9702636..ad70ccc6e 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 845414c61..000000000 --- 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 4fdd80c71..f28aafb4f 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 8473392e2..e58fa2483 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 c9d2b1f13..56aa255f2 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 553d23ba0..d704d4e19 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 000000000..950d39c08 --- /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 000000000..6e6bd3f6d --- /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 bf3d7646b..cd9a91927 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 c31c7cb7a..17df1d7d4 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 819e9a14f..000000000 --- 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 6bfc41104..000000000 --- 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 f2e6eb44c..eb34bc68d 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 37caa6e63..8e5a010ed 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 a3a1a18c6..b232a73e0 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 d25e3c184..29216b496 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 47484cfb9..a91672310 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 7ef512a63..d200b3af2 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 5983575e5..b1397135f 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 a5d68d643..c92f29776 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 3cfb000fa..f0aa754f1 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 ecaff7147..9a184d780 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 86aae89c3..0379adc15 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 91840cbbc..bf0dbd9d8 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 c892e8538..04c025efc 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 ba599c698..93bd6e73f 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 eb8fb05fe..29dc83e65 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 11f0323b3..9b93d5669 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 0d1d8cce4..45a93e843 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 381df6f10..e375eb25d 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 fca913f71..fa208100e 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 1e6cbd77d..97e7a94ec 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 5276596c3..1276d6348 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 4b60a32e7..7d25a8649 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 81d3e6e7d..b26931069 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 87d8cf665..6f9927c6a 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 723caa33f..14fddfc13 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 000000000..cf6d698c2 --- /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 c3a8511e2..cfa09e6e4 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 feedc3d07..ba475a8e4 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 58246a583..9c7523159 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 88194dfcc..e3a750ce5 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 1dd6339ed..d7544d1fe 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 b980fb593..16ee0077f 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 603dbc16a..5ae930fab 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 6ca22fbd7..b14dabdba 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 50b54fe2b..dacb0f6e1 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 2d49473b6..000000000 --- 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 000000000..def9ae492 --- /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 289a0536d..ce3339e4d 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 4c2e92935..bbaa536ce 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 c9b1260aa..163f0b8e8 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 df96a6352..3454a68bd 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 172126f77..e340fa8f2 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 91b722b66..afa8171c6 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 5d201b79b..ed8ec94fb 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 6114558a1..aedd130ce 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 6090ee2b4..468b1b4c0 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 45fac7686..554e2bf8c 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 3e4d3c35e..b7d6bdfe1 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 928294fa9..0de9a15f4 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 0852f45aa..55ba2b485 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 d26dbfe70..0fb1078d0 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 ff1667198..2b372ec45 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 4c2391ffc..8970f46ca 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 eaec2dba8..f44902d5a 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 6ac5bd0b9..db8ee3af5 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 ff176b2c6..cfe41817e 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 1d2419957..0caf6ff55 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 205cfef11..460b9e6f9 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 8dba4e06d..3dfbe1812 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 01bc3df03..01e259e75 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 aa6f5897d..f27303399 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 427367e71..54134fffc 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 b781174d1..ccc7e20c0 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 10a922dfd..4fbbf2a06 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 55e07d8b0..9d4975a02 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 6ba9a41ae..6c3a69322 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 c7bae1017..f7b78ea08 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 839da31eb..aa47dc97a 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 ae5c5cb44..3051bffea 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 3c517c28e..2181c428a 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 ba9889e62..21478b10c 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 e68e0c41b..88322a130 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 f2db9d84d..4c34f2e3c 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 d0399e313..b874bd6ed 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 2d1ea6abc..639b158e8 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 0978acbf4..215c03ab3 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 a0e118d80..e0490b9eb 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 781cee242..d08af3840 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 28d1ac58f..28d24d435 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 000000000..e91a851d3 --- /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 56d6e0be5..0a6c54e1d 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 883c799f0..b82715d7c 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 ed429b371..ba2411feb 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 09a198cce..0771b10c4 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 9ed495ad4..fbe434b1a 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 cef814261..8b69c523a 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 15cbc1fb0..1fa2f1d00 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 bae939a43..1f21b89ae 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 fd720e0fd..c154db24f 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 6c2add980..35c916ddb 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 8ee9b31f2..000000000 --- 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 a0bc52002..4e02470dc 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 a1725bf32..000000000 --- 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 26b679c51..000000000 --- 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 55ff9c130..75770301c 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 63217935b..db1822be9 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 c363f74de..b44e44f79 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 c79df3e70..0d47a85c0 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 8220803c6..2a314ece3 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 6c134c6cd..354c36f3e 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 ed162c7a7..97128341d 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 9c24abac8..aa223d192 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 9428ba61c..1af8f1ca3 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 d317d0f09..274d1be7d 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 6601622f3..2c8fbbf43 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 8d18ed90b..93202deef 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 0c6a1cc7d..3f7d1ccac 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 9fb6b623b..51ce661e8 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 2a9d194aa..811000a77 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 000000000..089e77cfa --- /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; +}