Skip to content

Commit

Permalink
Improve memory safety
Browse files Browse the repository at this point in the history
This commit makes numerous refinements to cosmopolitan memory handling.

The default stack size has been reduced from 2mb to 128kb. A new macro
is now provided so you can easily reconfigure the stack size to be any
value you want. Work around the breaking change by adding to your main:

    STATIC_STACK_SIZE(0x00200000);  // 2mb stack

If you're not sure how much stack you need, then you can use:

    STATIC_YOINK("stack_usage_logging");

After which you can `sort -nr o/$MODE/stack.log`. Based on the unit test
suite, nothing in the Cosmopolitan repository (except for Python) needs
a stack size greater than 30kb. There are also new macros for detecting
the size and address of the stack at runtime, e.g. GetStackAddr(). We
also now support sigaltstack() so if you want to see nice looking crash
reports whenever a stack overflow happens, you can put this in main():

    ShowCrashReports();

Under `make MODE=dbg` and `make MODE=asan` the unit testing framework
will now automatically print backtraces of memory allocations when
things like memory leaks happen. Bugs are now fixed in ASAN global
variable overrun detection. The memtrack and asan runtimes also handle
edge cases now. The new tools helped to identify a few memory leaks,
which are fixed by this change.

This change should fix an issue reported in #288 with ARG_MAX limits.
Fixing this doubled the performance of MKDEPS.COM and AR.COM yet again.
  • Loading branch information
jart committed Oct 14, 2021
1 parent a0b39f8 commit 226aaf3
Show file tree
Hide file tree
Showing 317 changed files with 6,448 additions and 3,967 deletions.
36 changes: 16 additions & 20 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -216,30 +216,25 @@ tags: TAGS HTAGS
o/$(MODE)/.x:
@mkdir -p $(@D) && touch $@

ifneq ($(findstring 4.,,$(MAKE_VERSION)),$(MAKE_VERSION))
o/$(MODE)/srcs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))
$(file >$@) $(foreach x,$(SRCS),$(file >>$@,$(x)))
o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x))))
$(file >$@) $(foreach x,$(HDRS) $(INCS),$(file >>$@,$(x)))
o/$(MODE)/incs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(INCS) $(INCS),$(dir $(x))))
$(file >$@) $(foreach x,$(INCS) $(INCS),$(file >>$@,$(x)))
else
o/$(MODE)/srcs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))
$(MAKE) MODE=rel -j8 -pn bopit 2>/dev/null | sed -ne '/^SRCS/ {s/.*:= //;s/ */\n/g;p;q}' >$@
$(file >$@,$(SRCS))
o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x))))
$(MAKE) MODE=rel -j8 -pn bopit 2>/dev/null | sed -ne '/^HDRS/ {s/.*:= //;s/ */\n/g;p;q}' >$@
$(file >$@,$(HDRS) $(INCS))
o/$(MODE)/incs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(INCS) $(INCS),$(dir $(x))))
$(MAKE) MODE=rel -j8 -pn bopit 2>/dev/null | sed -ne '/^INCS/ {s/.*:= //;s/ */\n/g;p;q}' >$@
endif

$(file >$@,$(INCS))
o/$(MODE)/depend: o/$(MODE)/.x o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt o/$(MODE)/incs.txt $(SRCS) $(HDRS) $(INCS)
@$(COMPILE) -AMKDEPS $(MKDEPS) -o $@ -r o/$(MODE)/ o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt o/$(MODE)/incs.txt
@$(COMPILE) -AMKDEPS $(MKDEPS) -o $@ -r o/$(MODE)/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt @o/$(MODE)/incs.txt

TAGS: o/$(MODE)/srcs.txt $(SRCS)
o/$(MODE)/srcs-old.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))
$(file >$@) $(foreach x,$(SRCS),$(file >>$@,$(x)))
o/$(MODE)/hdrs-old.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x))))
$(file >$@) $(foreach x,$(HDRS) $(INCS),$(file >>$@,$(x)))

TAGS: o/$(MODE)/srcs-old.txt $(SRCS)
@rm -f $@
@$(COMPILE) -ATAGS -T$@ $(TAGS) $(TAGSFLAGS) -L $< -o $@

HTAGS: o/$(MODE)/hdrs.txt $(HDRS)
HTAGS: o/$(MODE)/hdrs-old.txt $(HDRS)
@rm -f $@
@$(COMPILE) -ATAGS -T$@ build/htags -L $< -o $@

Expand Down Expand Up @@ -326,14 +321,15 @@ COSMOPOLITAN_HEADERS = \
THIRD_PARTY_ZLIB \
THIRD_PARTY_REGEX

o/$(MODE)/cosmopolitan.a.txt:
printf "%s\n" $(call reverse,$(call uniq,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)))))
o/$(MODE)/cosmopolitan.a: $(filter-out o/libc/stubs/exit11.o,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_A_OBJS)))
o/$(MODE)/cosmopolitan.a: \
$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_A_OBJS))

o/cosmopolitan.h: \
o/$(MODE)/tool/build/rollup.com \
libc/integral/normalize.inc \
$(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_HDRS))
@$(COMPILE) -AROLLUP -T$@ $^ >$@
$(file >$@.args,libc/integral/normalize.inc $(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_HDRS)))
@$(COMPILE) -AROLLUP -T$@ o/$(MODE)/tool/build/rollup.com @$@.args >$@

o/cosmopolitan.html: \
o/$(MODE)/third_party/chibicc/chibicc.com.dbg \
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,4 @@ find o -name \*.com | xargs ls -rShal | less
| FreeBSD | 12 | 2018 |
| OpenBSD | 6.4 | 2018 |
| NetBSD | 9.1 | 2020 |
| GNU Make | 3.80 | 2010 |
| GNU Make | 4.0 | 2015 |
4 changes: 2 additions & 2 deletions ape/ape.lds
Original file line number Diff line number Diff line change
Expand Up @@ -485,10 +485,10 @@ HIDDEN(ape_ram_align = PAGESIZE);
HIDDEN(ape_ram_rva = RVA(ape_ram_vaddr));

HIDDEN(ape_stack_offset = ape_ram_offset + ape_ram_filesz);
HIDDEN(ape_stack_vaddr = 0x700000000000 - STACKSIZE);
HIDDEN(ape_stack_vaddr = DEFINED(ape_stack_vaddr) ? ape_stack_vaddr : 0x700000000000 - STACKSIZE);
HIDDEN(ape_stack_paddr = ape_ram_paddr + ape_ram_filesz);
HIDDEN(ape_stack_filesz = 0);
HIDDEN(ape_stack_memsz = STACKSIZE);
HIDDEN(ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : STACKSIZE);
HIDDEN(ape_stack_align = 16);

HIDDEN(ape_note_offset = ape_rom_offset + (ape_note - ape_rom_vaddr));
Expand Down
10 changes: 10 additions & 0 deletions ape/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef COSMOPOLITAN_APE_CONFIG_H_
#define COSMOPOLITAN_APE_CONFIG_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)

#define STATIC_SYMBOL(NAME, VALUE) \
asm(".equ\t" NAME "," VALUE "\n\t" \
".globl\t" NAME)

#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_APE_CONFIG_H_ */
38 changes: 19 additions & 19 deletions ape/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,59 +68,59 @@ static wontreturn void Exit(int os, long rc) {
}

static void Close(int os, long fd) {
long ax;
long ax, di;
asm volatile("syscall"
: "=a"(ax)
: "0"(__NR_close), "D"(fd)
: "=a"(ax), "=D"(di)
: "0"(__NR_close), "1"(fd)
: "rcx", "rdx", "rsi", "r8", "r9", "r10", "r11", "memory", "cc");
}

static long Read(int os, long fd, void *data, unsigned long size) {
bool cf;
long ax;
long ax, di, si, dx;
asm volatile("clc\n\t"
"syscall"
: "=@ccc"(cf), "=a"(ax)
: "1"(__NR_read), "D"(fd), "S"(data), "d"(size)
: "=@ccc"(cf), "=a"(ax), "=D"(di), "=S"(si), "=d"(dx)
: "1"(__NR_read), "2"(fd), "3"(data), "4"(size)
: "rcx", "r8", "r9", "r10", "r11", "memory");
if (cf) ax = -ax;
return ax;
}

static void Write(int os, long fd, const void *data, unsigned long size) {
long ax;
long ax, di, si, dx;
asm volatile("syscall"
: "=a"(ax)
: "0"(__NR_write), "D"(fd), "S"(data), "d"(size)
: "=a"(ax), "=D"(di), "=S"(si), "=d"(dx)
: "0"(__NR_write), "1"(fd), "2"(data), "3"(size)
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
}

static long Fstat(int os, long fd, union metastat *st) {
long ax;
long ax, di, si;
asm volatile("syscall"
: "=a"(ax)
: "0"(__NR_fstat), "D"(fd), "S"(st)
: "rcx", "rdx", "r8", "r9", "r10", "r11", "memory");
: "=a"(ax), "=D"(di), "=S"(si)
: "0"(__NR_fstat), "1"(fd), "2"(st)
: "rcx", "rdx", "r8", "r9", "r10", "r11", "memory", "cc");
return ax;
}

static void Msyscall(int os, long p, long n) {
long ax;
long ax, di, si;
if (os == OPENBSD) {
asm volatile("syscall"
: "=a"(ax)
: "0"(37), "D"(p), "S"(n)
: "=a"(ax), "=D"(di), "=S"(si)
: "0"(37), "1"(p), "2"(n)
: "rcx", "rdx", "r8", "r9", "r10", "r11", "memory", "cc");
}
}

static long Open(int os, const char *path, long flags, long mode) {
bool cf;
long ax;
long ax, di, si, dx;
asm volatile("clc\n\t"
"syscall"
: "=@ccc"(cf), "=a"(ax)
: "1"(__NR_open), "D"(path), "S"(flags), "d"(mode)
: "=@ccc"(cf), "=a"(ax), "=D"(di), "=S"(si), "=d"(dx)
: "1"(__NR_open), "2"(path), "3"(flags), "4"(mode)
: "rcx", "r8", "r9", "r10", "r11", "memory");
if (cf) ax = -ax;
return ax;
Expand Down
Binary file modified build/bootstrap/ar.com
Binary file not shown.
Binary file modified build/bootstrap/mkdeps.com
Binary file not shown.
5 changes: 3 additions & 2 deletions build/config.mk
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ CONFIG_CPPFLAGS += \

CONFIG_CCFLAGS += \
$(BACKTRACES) \
$(FTRACE) \
-O3

TARGET_ARCH ?= \
Expand Down Expand Up @@ -122,7 +123,8 @@ CONFIG_CPPFLAGS += \
CONFIG_CCFLAGS += \
$(BACKTRACES) \
$(FTRACE) \
-O2
-O2 \
-fno-inline

CONFIG_COPTS += \
-fsanitize=address
Expand Down Expand Up @@ -159,7 +161,6 @@ CONFIG_CCFLAGS += \
-fno-align-labels \
-fno-align-loops \
-fschedule-insns2 \
-fomit-frame-pointer \
-momit-leaf-frame-pointer \
-foptimize-sibling-calls
TARGET_ARCH ?= \
Expand Down
7 changes: 5 additions & 2 deletions build/definitions.mk
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ export TMPDIR
FTRACE = \
-pg

BACKTRACES = \
-fno-optimize-sibling-calls \
-mno-omit-leaf-frame-pointer

SANITIZER = \
-fsanitize=address

Expand Down Expand Up @@ -126,8 +130,7 @@ DEFAULT_COPTS = \
-fstrict-aliasing \
-fstrict-overflow \
-fno-omit-frame-pointer \
-fno-semantic-interposition \
-mno-omit-leaf-frame-pointer
-fno-semantic-interposition

MATHEMATICAL = \
-O3 \
Expand Down
6 changes: 4 additions & 2 deletions build/rules.mk
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

MAKEFLAGS += --no-builtin-rules

o/%.a: ; @$(COMPILE) -AARCHIVE -T$@ $(AR) $(ARFLAGS) $@ $^
o/%.o: %.s ; @$(COMPILE) -AOBJECTIFY.s $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
o/%.o: o/%.s ; @$(COMPILE) -AOBJECTIFY.s $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
o/%.s: %.S ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) $<
Expand All @@ -36,7 +35,6 @@ o/%.h.okk: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.cxx) -xc++
o/%.greg.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
o/%.zip.o: o/% ; @$(COMPILE) -AZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<

o/$(MODE)/%.a: ; @$(COMPILE) -AARCHIVE -T$@ $(AR) $(ARFLAGS) $@ $^
o/$(MODE)/%: o/$(MODE)/%.dbg ; @$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S -O binary $< $@
o/$(MODE)/%.o: %.s ; @$(COMPILE) -AOBJECTIFY.s $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
o/$(MODE)/%.o: o/$(MODE)/%.s ; @$(COMPILE) -AOBJECTIFY.s $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
Expand Down Expand Up @@ -82,6 +80,10 @@ o/$(MODE)/%-gcc.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S
o/$(MODE)/%-clang.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $<
o/$(MODE)/%-clang.asm: CC = $(CLANG)

o/%.a:
$(file >$@.args,$^)
@$(COMPILE) -AARCHIVE -T$@ $(AR) $(ARFLAGS) $@ @$@.args

o/$(MODE)/%.o: %.py o/$(MODE)/third_party/python/pyobj.com
@$(COMPILE) -APYOBJ o/$(MODE)/third_party/python/pyobj.com $(PYFLAGS) -o $@ $<

Expand Down
3 changes: 2 additions & 1 deletion dsp/tty/rgb2ansi.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ __m128 tty2rgbf_(struct TtyRgb rgbxt) {

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);
gray = round(871024 / 4096299. * r + 8788810 / 12288897. * g +
887015 / 12288897. * b);
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;
Expand Down
1 change: 1 addition & 0 deletions examples/ctrlc.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/calls/calls.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/errno.h"
#include "libc/log/check.h"
#include "libc/log/color.internal.h"
Expand Down
1 change: 1 addition & 0 deletions examples/getrandom.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#endif
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/log/check.h"
Expand Down
1 change: 1 addition & 0 deletions examples/rusage.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "libc/calls/calls.h"
#include "libc/calls/sigbits.h"
#include "libc/calls/struct/rusage.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/errno.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
Expand Down
77 changes: 77 additions & 0 deletions examples/stackoverflow.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
│ To the extent possible under law, Justine Tunney has waived │
│ all copyright and related or neighboring rights to this file, │
│ as it is written in the following disclaimers: │
│ • http://unlicense.org/ │
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/calls/calls.h"
#include "libc/limits.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/runtime/stack.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/prot.h"

/**
* @fileoverview Stack Overflow Demo
*/

#define N INT_MAX

STATIC_STACK_SIZE(FRAMESIZE);

int A(int f(), int n) {
if (n < N) {
return f(f, n + 1) - 1;
} else {
return N;
}
}

int (*Ap)(int (*)(), int) = A;

int main(int argc, char *argv[]) {
ShowCrashReports();
return !!Ap(Ap, 0);
}

/*
error: Uncaught SIGSEGV (Stack Overflow) on rhel5 pid 368
./o//examples/stackoverflow.com
EUNKNOWN[No error information][0]
Linux rhel5 2.6.18-8.el5 #1 SMP Thu Mar 15 19:46:53 EDT 2007
0x0000000000406896: A at examples/stackoverflow.c:24
0x0000000000406898: A at examples/stackoverflow.c:24
0x0000000000406898: A at examples/stackoverflow.c:24
0x0000000000406898: A at examples/stackoverflow.c:24
0x0000000000406898: A at examples/stackoverflow.c:24
0x0000000000406898: A at examples/stackoverflow.c:24
0x0000000000406898: A at examples/stackoverflow.c:24
0x0000000000406898: A at examples/stackoverflow.c:24
0x0000000000406898: A at examples/stackoverflow.c:24
etc. etc.
RAX 0000000000000000 RBX 0000000000000001 RDI 000000000040687e ST(0) 0.0
RCX 0000000000417125 RDX 000000000041cd70 RSI 0000000000000efe ST(1) 0.0
RBP 00006ffffffe1000 RSP 00006ffffffe1000 RIP 0000000000406897 ST(2) 0.0
R8 0000000000000000 R9 0000000000000022 R10 0000000000000008 ST(3) 0.0
R11 0000000000000293 R12 0000000000000001 R13 00007ffc70b4fc48 ST(4) 0.0
R14 00007ffc70b4fc58 R15 00007ffc70b4fd18 VF IF
XMM0 00000000000000000000000000000000 XMM8 00000000000000000000000000000000
XMM1 ffffffffffffeb030000000000000000 XMM9 00000000000000000000000000000000
XMM2 0000000000000000ffffffffffffffff XMM10 00000000000000000000000000000000
XMM3 00000000000000000000000000000000 XMM11 00000000000000000000000000000000
XMM4 00000000000000000000000000000000 XMM12 00000000000000000000000000000000
XMM5 00000000000000000000000000000000 XMM13 00000000000000000000000000000000
XMM6 00000000000000000000000000000000 XMM14 00000000000000000000000000000000
XMM7 00000000000000000000000000000000 XMM15 00000000000000000000000000000000
100080000000-100080030000 rw-pa-- 3x automap
6ffffffe0000-6fffffff0000 rw-paSF 1x stack
# 4 frames mapped w/ 0 frames gapped
*/
Loading

0 comments on commit 226aaf3

Please sign in to comment.