Rewrite .zip.o file linker

This change takes an entirely new approach to the incremental linking of
pkzip executables. The assets created by zipobj.com are now treated like
debug data. After a .com.dbg is compiled, fixupobj.com should be run, so
it can apply fixups to the offsets and move the zip directory to the end
of the file. Since debug data doesn't get objcopy'd, a new tool has been
introduced called zipcopy.com which should be run after objcopy whenever
a .com file is created. This is all automated by the `cosmocc` toolchain
which is rapidly becoming the new recommended approach.

This change also introduces the new C23 checked arithmetic macros.
This commit is contained in:
Justine Tunney 2023-06-10 09:15:19 -07:00
parent f6407d5f7c
commit 8ff48201ca
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
125 changed files with 1056 additions and 928 deletions

View file

@ -426,7 +426,9 @@ toolchain: o/cosmopolitan.h \
o/$(MODE)/ape/ape-copy-self.o \
o/$(MODE)/ape/ape-no-modify-self.o \
o/$(MODE)/cosmopolitan.a \
o/$(MODE)/third_party/libcxx/libcxx.a
o/$(MODE)/third_party/libcxx/libcxx.a \
o/$(MODE)/tool/build/fixupobj.com \
o/$(MODE)/tool/build/zipcopy.com
aarch64: private .INTERNET = true
aarch64: private .UNSANDBOXED = true

View file

@ -2,7 +2,6 @@
│vi: set et sts=2 tw=2 fenc=utf-8 :vi│
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/thread/tls.h"
#include "libc/zip.internal.h"
ENTRY(_start)
OUTPUT_ARCH(aarch64)
@ -201,11 +200,6 @@ SECTIONS {
_edata = .;
PROVIDE(edata = .);
.zip : {
KEEP(*(SORT_BY_NAME(.zip.*)))
HIDDEN(_ezip = .);
}
. = .;
__bss_start = .;
__bss_start__ = .;
@ -259,6 +253,14 @@ SECTIONS {
.ARM.attributes 0 : { KEEP(*(.ARM.attributes)) KEEP(*(.gnu.attributes)) }
.note.gnu.arm.ident 0 : { KEEP(*(.note.gnu.arm.ident)) }
.zip 0 : {
KEEP(*(.zip.file))
__zip_cdir_start = .;
KEEP(*(.zip.cdir))
__zip_cdir_size = . - __zip_cdir_start;
KEEP(*(.zip.eocd))
}
/DISCARD/ : {
*(__patchable_function_entries)
*(.GCC.command.line)
@ -279,15 +281,6 @@ _tbss_size = _tbss_end - _tbss_start;
_tbss_offset = _tbss_start - _tdata_start;
_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start);
_tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
__zip_start_rva = DEFINED(__zip_start) ? __zip_start - __executable_start : 0;
/* ZIP End of Central Directory header */
#define ZIPCONST(NAME, VAL) NAME = DEFINED(__zip_start) ? VAL : 0;
ZIPCONST(v_zip_cdoffset, __zip_start - __executable_start);
ZIPCONST(v_zip_cdirsize, __zip_end - __zip_start);
ASSERT(v_zip_cdirsize % kZipCdirHdrLinkableSize == 0, "bad zip cdir");
ZIPCONST(v_zip_records, v_zip_cdirsize / kZipCdirHdrLinkableSize);
ZIPCONST(v_zip_commentsize, _ezip - __zip_end - kZipCdirHdrMinSize);
ASSERT(ALIGNOF(.tdata) <= TLS_ALIGNMENT && ALIGNOF(.tbss) <= TLS_ALIGNMENT,
"_Thread_local _Alignof can't exceed TLS_ALIGNMENT");

View file

@ -182,7 +182,6 @@
#include "libc/nt/pedef.internal.h"
#include "libc/thread/tls.h"
#include "ape/ape.internal.h"
#include "libc/zip.internal.h"
/* uncomment if .com.dbg won't execute on your kernel (will break .com file) */
/* #define APE_FIX_COM_DBG */
@ -373,6 +372,8 @@ SECTIONS {
/*END: Read Only Data (only needed for initialization) */
} :Rom
. = DATA_SEGMENT_ALIGN(4096, 4096);
/* initialization image for thread-local storage, this is copied */
/* out to actual TLS areas at runtime, so just make it read-only */
.tdata . : {
@ -424,8 +425,7 @@ SECTIONS {
/*END: NT FORK COPYING */
HIDDEN(_edata = .);
PROVIDE_HIDDEN(edata = .);
KEEP(*(SORT_BY_NAME(.zip.*)))
HIDDEN(_ezip = .);
HIDDEN(_ezip = .); /* <-- very deprecated */
. = ALIGN(4096);
} :Ram
@ -457,6 +457,8 @@ SECTIONS {
PROVIDE_HIDDEN(end = .);
} :Bss
. = DATA_SEGMENT_END(.);
/*END: nt addressability guarantee */
/*END: bsd addressability guarantee */
/*END: linux addressability guarantee */
@ -498,6 +500,14 @@ SECTIONS {
.gnu.attributes 0 : { KEEP(*(.gnu.attributes)) }
.GCC.command.line 0 : { *(.GCC.command.line) }
.zip 0 : {
KEEP(*(.zip.file))
__zip_cdir_start = .;
KEEP(*(.zip.cdir))
__zip_cdir_size = . - __zip_cdir_start;
KEEP(*(.zip.eocd))
}
/DISCARD/ : {
*(__patchable_function_entries)
*(__mcount_loc)
@ -643,15 +653,6 @@ HIDDEN(v_ape_highsectors = MIN(0xffff, v_ape_allsectors - v_ape_realsectors));
TSSDESCSTUB2(_tss, _tss, _tss_end ? _tss_end - _tss - 1 : 0);
#endif
/* ZIP End of Central Directory header */
#define ZIPCONST(NAME, VAL) HIDDEN(NAME = DEFINED(__zip_start) ? VAL : 0);
ZIPCONST(v_zip_cdoffset, __zip_start - IMAGE_BASE_VIRTUAL);
ZIPCONST(v_zip_cdoffset, __zip_start - IMAGE_BASE_VIRTUAL);
ZIPCONST(v_zip_cdirsize, __zip_end - __zip_start);
ASSERT(v_zip_cdirsize % kZipCdirHdrLinkableSize == 0, "bad zip cdir");
ZIPCONST(v_zip_records, v_zip_cdirsize / kZipCdirHdrLinkableSize);
ZIPCONST(v_zip_commentsize, _ezip - __zip_end - kZipCdirHdrMinSize);
#if SupportsXnu()
/* Generates deterministic ID. */
#define PHI 0x9e3779b9925d4c17

View file

@ -28,7 +28,12 @@ APELINK = \
-ALINK.ape \
$(LINK) \
$(LINKARGS) \
$(OUTPUT_OPTION)
$(OUTPUT_OPTION) && \
$(COMPILE) \
-AFIXUP.ape \
-wT$@ \
$(FIXUPOBJ) \
$@
APE_SRCS = ape/ape.S
APE_OBJS = o/$(MODE)/ape/ape.o
@ -40,7 +45,7 @@ o/$(MODE)/ape: $(APE)
o/$(MODE)/ape/aarch64.lds: \
ape/aarch64.lds \
libc/zip.h \
libc/zip.internal.h \
libc/intrin/bits.h \
libc/thread/tls.h \
libc/calls/struct/timespec.h \
@ -57,7 +62,12 @@ APELINK = \
-ALINK.ape \
$(LINK) \
$(LINKARGS) \
$(OUTPUT_OPTION)
$(OUTPUT_OPTION) && \
$(COMPILE) \
-AFIXUP.ape \
-wT$@ \
$(FIXUPOBJ) \
$@
APE_NO_MODIFY_SELF = \
o/$(MODE)/ape/ape.lds \
@ -106,7 +116,7 @@ o/$(MODE)/ape/public/ape.lds: \
libc/macros.internal.h \
libc/nt/pedef.internal.h \
libc/str/str.h \
libc/zip.h
libc/zip.internal.h
o/ape/idata.inc: \
ape/idata.internal.h \
@ -185,17 +195,25 @@ o/$(MODE)/ape/loader-xnu-clang.asm: ape/loader.c
o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg
o/$(MODE)/ape/ape.macho: o/$(MODE)/ape/ape.macho.dbg
o/$(MODE)/ape/ape.elf.dbg: private \
LDFLAGS += \
-z common-page-size=0x10 \
-z max-page-size=0x10
o/$(MODE)/ape/ape.elf.dbg: \
o/$(MODE)/ape/loader.o \
o/$(MODE)/ape/loader-elf.o \
ape/loader.lds
@$(ELFLINK) -z common-page-size=0x10 -z max-page-size=0x10
@$(ELFLINK)
o/$(MODE)/ape/ape.macho.dbg: private \
LDFLAGS += \
-z common-page-size=0x10 \
-z max-page-size=0x10
o/$(MODE)/ape/ape.macho.dbg: \
o/$(MODE)/ape/loader-xnu.o \
o/$(MODE)/ape/loader-macho.o \
ape/loader-macho.lds
@$(ELFLINK) -z common-page-size=0x10 -z max-page-size=0x10
@$(ELFLINK)
.PHONY: o/$(MODE)/ape
o/$(MODE)/ape: $(APE_CHECKS) \
@ -232,4 +250,4 @@ o/$(MODE)/ape/ape.lds: \
libc/macros.internal.h \
libc/nt/pedef.internal.h \
libc/str/str.h \
libc/zip.h
libc/zip.internal.h

View file

@ -19,8 +19,6 @@ extern unsigned char _tbss_end[] __attribute__((__weak__));
extern unsigned char _tls_align[] __attribute__((__weak__));
extern unsigned char __test_start[] __attribute__((__weak__));
extern unsigned char __ro[] __attribute__((__weak__));
extern uint8_t __zip_start[] __attribute__((__weak__));
extern uint8_t __zip_end[] __attribute__((__weak__));
extern uint8_t __data_start[] __attribute__((__weak__));
extern uint8_t __data_end[] __attribute__((__weak__));
extern uint8_t __bss_start[] __attribute__((__weak__));

Binary file not shown.

Binary file not shown.

BIN
build/bootstrap/zipcopy.com Executable file

Binary file not shown.

Binary file not shown.

View file

@ -74,6 +74,7 @@ TOUCH = build/bootstrap/touch.com
PKG = build/bootstrap/package.com
MKDEPS = build/bootstrap/mkdeps.com
ZIPOBJ = build/bootstrap/zipobj.com
ZIPCOPY = build/bootstrap/zipcopy.com
FIXUPOBJ = build/bootstrap/fixupobj.com
MKDIR = build/bootstrap/mkdir.com -p
COMPILE = build/bootstrap/compile.com -V9 -P4096 $(QUOTA)
@ -258,12 +259,6 @@ DEFAULT_LDFLAGS += \
-zcommon-page-size=0x1000
endif
ZIPOBJ_FLAGS = \
-b$(IMAGE_BASE_VIRTUAL)
PYFLAGS = \
-b$(IMAGE_BASE_VIRTUAL)
ASONLYFLAGS = \
-c \
-g \
@ -372,7 +367,7 @@ PREPROCESS = $(CC) $(PREPROCESS.flags)
PREPROCESS.lds = $(CC) $(PREPROCESS.lds.flags)
LINK = $(LD) $(LINK.flags)
ELF = o/libc/elf/elf.lds
ELFLINK = $(COMPILE) -ALINK.elf $(LINK) $(LINKARGS) $(OUTPUT_OPTION)
ELFLINK = $(COMPILE) -ALINK.elf $(LINK) $(LINKARGS) $(OUTPUT_OPTION) && $(COMPILE) -AFIXUP.ape -T$@ $(FIXUPOBJ) $@
LINKARGS = $(patsubst %.lds,-T %.lds,$(call uniqr,$(LD.libs) $(filter-out %.pkg,$^)))
LOLSAN = build/lolsan -b $(IMAGE_BASE_VIRTUAL)

View file

@ -16,10 +16,11 @@
MAKEFLAGS += --no-builtin-rules
MAKE_ZIPCOPY = $(COMPILE) -AZIPCOPY -wT$@ $(ZIPCOPY) $< $@
ifneq ($(ARCH), aarch64)
MAKE_OBJCOPY = $(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S -O binary $< $@
MAKE_OBJCOPY = $(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S -O binary $< $@ && $(MAKE_ZIPCOPY)
else
MAKE_OBJCOPY = $(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S $< $@
MAKE_OBJCOPY = $(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S $< $@ && $(MAKE_ZIPCOPY)
endif
o/%.lds: %.lds ; @$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $<

View file

@ -36,6 +36,7 @@
#include "libc/nt/runtime.h"
#include "libc/nt/struct/byhandlefileinformation.h"
#include "libc/nt/struct/overlapped.h"
#include "libc/stdckdint.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/f.h"
#include "libc/sysv/consts/fd.h"
@ -149,7 +150,7 @@ static textwindows int sys_fcntl_nt_lock(struct Fd *f, int fd, int cmd,
len = INT64_MAX - off;
}
if (off < 0 || len < 0 || __builtin_add_overflow(off, len, &end)) {
if (off < 0 || len < 0 || ckd_add(&end, off, len)) {
return einval();
}

View file

@ -22,6 +22,7 @@
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/stdckdint.h"
#include "libc/sysv/errfuns.h"
/**
@ -34,8 +35,8 @@
int getgroups(int size, uint32_t list[]) {
int rc;
size_t n;
if (IsAsan() && (__builtin_mul_overflow(size, sizeof(list[0]), &n) ||
!__asan_is_valid(list, n))) {
if (IsAsan() &&
(ckd_mul(&n, size, sizeof(list[0])) || !__asan_is_valid(list, n))) {
rc = efault();
} else if (IsLinux() || IsNetbsd() || IsOpenbsd() || IsFreebsd() || IsXnu()) {
rc = sys_getgroups(size, list);

View file

@ -64,6 +64,7 @@ textstartup noasan void InitializeMetalFile(void) {
* user code can STATIC_YOINK this symbol.
*/
size_t size = ROUNDUP(_ezip - __executable_start, 4096);
// TODO(jart): Restore support for ZIPOS on metal.
void *copied_base;
struct DirectMap dm;
dm = sys_mmap_metal(NULL, size, PROT_READ | PROT_WRITE,

View file

@ -54,7 +54,7 @@
*
* If your main() source file has this statement:
*
* STATIC_YOINK("zip_uri_support");
* STATIC_YOINK("zipos");
*
* Then you can read zip assets by adding a `"/zip/..."` prefix to `file`, e.g.
*

View file

@ -22,6 +22,7 @@
#include "libc/intrin/strace.internal.h"
#include "libc/sock/struct/pollfd.h"
#include "libc/sock/struct/pollfd.internal.h"
#include "libc/stdckdint.h"
#include "libc/sysv/errfuns.h"
/**
@ -69,8 +70,8 @@ int poll(struct pollfd *fds, size_t nfds, int timeout_ms) {
uint64_t millis;
BEGIN_CANCELLATION_POINT;
if (IsAsan() && (__builtin_mul_overflow(nfds, sizeof(struct pollfd), &n) ||
!__asan_is_valid(fds, n))) {
if (IsAsan() &&
(ckd_mul(&n, nfds, sizeof(struct pollfd)) || !__asan_is_valid(fds, n))) {
rc = efault();
} else if (!IsWindows()) {
if (!IsMetal()) {

View file

@ -27,6 +27,7 @@
#include "libc/intrin/strace.internal.h"
#include "libc/sock/struct/pollfd.h"
#include "libc/sock/struct/pollfd.internal.h"
#include "libc/stdckdint.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
@ -67,10 +68,10 @@ int ppoll(struct pollfd *fds, size_t nfds, const struct timespec *timeout,
struct timespec ts, *tsp;
BEGIN_CANCELLATION_POINT;
if (IsAsan() && (__builtin_mul_overflow(nfds, sizeof(struct pollfd), &n) ||
!__asan_is_valid(fds, n) ||
(timeout && !__asan_is_valid(timeout, sizeof(timeout))) ||
(sigmask && !__asan_is_valid(sigmask, sizeof(sigmask))))) {
if (IsAsan() &&
(ckd_mul(&n, nfds, sizeof(struct pollfd)) || !__asan_is_valid(fds, n) ||
(timeout && !__asan_is_valid(timeout, sizeof(timeout))) ||
(sigmask && !__asan_is_valid(sigmask, sizeof(sigmask))))) {
rc = efault();
} else if (!IsWindows()) {
e = errno;
@ -84,8 +85,7 @@ int ppoll(struct pollfd *fds, size_t nfds, const struct timespec *timeout,
if (rc == -1 && errno == ENOSYS) {
errno = e;
if (!timeout ||
__builtin_add_overflow(timeout->tv_sec, timeout->tv_nsec / 1000000,
&millis)) {
ckd_add(&millis, timeout->tv_sec, timeout->tv_nsec / 1000000)) {
millis = -1;
}
if (sigmask) sys_sigprocmask(SIG_SETMASK, sigmask, &oldmask);
@ -93,8 +93,8 @@ int ppoll(struct pollfd *fds, size_t nfds, const struct timespec *timeout,
if (sigmask) sys_sigprocmask(SIG_SETMASK, &oldmask, 0);
}
} else {
if (!timeout || __builtin_add_overflow(
timeout->tv_sec, timeout->tv_nsec / 1000000, &millis)) {
if (!timeout ||
ckd_add(&millis, timeout->tv_sec, timeout->tv_nsec / 1000000)) {
millis = -1;
}
rc = sys_poll_nt(fds, nfds, &millis, sigmask);

View file

@ -22,6 +22,7 @@
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/stdckdint.h"
#include "libc/sysv/errfuns.h"
/**
@ -40,8 +41,8 @@
int setgroups(size_t size, const uint32_t list[]) {
int rc;
size_t n;
if (IsAsan() && (__builtin_mul_overflow(size, sizeof(list[0]), &n) ||
!__asan_is_valid(list, n))) {
if (IsAsan() &&
(ckd_mul(&n, size, sizeof(list[0])) || !__asan_is_valid(list, n))) {
rc = efault();
} else if (IsLinux() || IsNetbsd() || IsOpenbsd() || IsFreebsd() || IsXnu()) {
rc = sys_setgroups(size, list);

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/struct/timespec.h"
#include "libc/limits.h"
#include "libc/stdckdint.h"
/**
* Reduces `ts` from 1e-9 to 1e-6 granularity w/ ceil rounding.
@ -45,8 +46,7 @@ int64_t timespec_tomicros(struct timespec ts) {
}
}
// convert to scalar result
if (!__builtin_mul_overflow(ts.tv_sec, 1000000ul, &us) &&
!__builtin_add_overflow(us, ts.tv_nsec, &us)) {
if (!ckd_mul(&us, ts.tv_sec, 1000000ul) && !ckd_add(&us, us, ts.tv_nsec)) {
return us;
} else if (ts.tv_sec < 0) {
return INT64_MIN;

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/struct/timespec.h"
#include "libc/limits.h"
#include "libc/stdckdint.h"
/**
* Reduces `ts` from 1e-9 to 1e-3 granularity w/ ceil rounding.
@ -44,8 +45,7 @@ int64_t timespec_tomillis(struct timespec ts) {
}
}
// convert to scalar result
if (!__builtin_mul_overflow(ts.tv_sec, 1000ul, &ms) &&
!__builtin_add_overflow(ms, ts.tv_nsec, &ms)) {
if (!ckd_mul(&ms, ts.tv_sec, 1000ul) && !ckd_add(&ms, ms, ts.tv_nsec)) {
return ms;
} else if (ts.tv_sec < 0) {
return INT64_MIN;

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/struct/timespec.h"
#include "libc/limits.h"
#include "libc/stdckdint.h"
/**
* Converts timespec to scalar.
@ -30,8 +31,7 @@
*/
int64_t timespec_tonanos(struct timespec x) {
int64_t ns;
if (!__builtin_mul_overflow(x.tv_sec, 1000000000ul, &ns) &&
!__builtin_add_overflow(ns, x.tv_nsec, &ns)) {
if (!ckd_mul(&ns, x.tv_sec, 1000000000ul) && !ckd_add(&ns, ns, x.tv_nsec)) {
return ns;
} else if (x.tv_sec < 0) {
return INT64_MIN;

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/struct/timeval.h"
#include "libc/limits.h"
#include "libc/stdckdint.h"
/**
* Converts timeval to scalar.
@ -30,8 +31,7 @@
*/
int64_t timeval_tomicros(struct timeval x) {
int64_t ns;
if (!__builtin_mul_overflow(x.tv_sec, 1000000ul, &ns) &&
!__builtin_add_overflow(ns, x.tv_usec, &ns)) {
if (!ckd_mul(&ns, x.tv_sec, 1000000ul) && !ckd_add(&ns, ns, x.tv_usec)) {
return ns;
} else if (x.tv_sec < 0) {
return INT64_MIN;

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/struct/timeval.h"
#include "libc/limits.h"
#include "libc/stdckdint.h"
/**
* Reduces `ts` from 1e-6 to 1e-3 granularity w/ ceil rounding.
@ -45,8 +46,7 @@ int64_t timeval_tomillis(struct timeval ts) {
}
}
// convert to scalar result
if (!__builtin_mul_overflow(ts.tv_sec, 1000ul, &ms) &&
!__builtin_add_overflow(ms, ts.tv_usec, &ms)) {
if (!ckd_mul(&ms, ts.tv_sec, 1000ul) && !ckd_add(&ms, ms, ts.tv_usec)) {
return ms;
} else if (ts.tv_sec < 0) {
return INT64_MIN;

View file

@ -1,36 +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/calls/calls.h"
// TODO(jart): DELETE
/**
* Deletes file.
*
* The caller's variable is made NULL. Note that we define unlink(NULL)
* as a no-op.
*
* @return 0 on success, or -1 w/ errno
* @asyncsignalsafe
*/
int unlink_s(const char **namep) {
const char *name = *namep;
*namep = 0;
return unlink(name);
}

View file

@ -27,14 +27,9 @@
#include "libc/intrin/bits.h"
#include "libc/intrin/strace.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/auxv.h"
static inline int CompareStrings(const char *l, const char *r) {
size_t i = 0;
while (l[i] == r[i] && r[i]) ++i;
return (l[i] & 255) - (r[i] & 255);
}
static inline int CheckDsoSymbolVersion(Elf64_Verdef *vd, int sym,
const char *name, char *strtab) {
Elf64_Verdaux *aux;
@ -42,7 +37,7 @@ static inline int CheckDsoSymbolVersion(Elf64_Verdef *vd, int sym,
if (!(vd->vd_flags & VER_FLG_BASE) &&
(vd->vd_ndx & 0x7fff) == (sym & 0x7fff)) {
aux = (Elf64_Verdaux *)((char *)vd + vd->vd_aux);
return !CompareStrings(name, strtab + aux->vda_name);
return !strcmp(name, strtab + aux->vda_name);
}
if (!vd->vd_next) {
return 0;
@ -138,7 +133,7 @@ void *__vdsosym(const char *version, const char *name) {
if (!symtab[i].st_shndx) {
continue;
}
if (CompareStrings(name, strtab + symtab[i].st_name)) {
if (strcmp(name, strtab + symtab[i].st_name)) {
continue;
}
if (versym && !CheckDsoSymbolVersion(verdef, versym[i], version, strtab)) {

View file

@ -1,33 +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/elf/elf.h"
#include "libc/intrin/kprintf.h"
#include "libc/runtime/runtime.h"
void CheckElfAddress(const Elf64_Ehdr *elf, size_t mapsize, intptr_t addr,
size_t addrsize) {
#if !(TRUSTWORTHY + ELF_TRUSTWORTHY + 0) || ELF_UNTRUSTWORTHY + 0
if (addr < (intptr_t)elf || addr + addrsize > (intptr_t)elf + mapsize) {
kprintf("%p-%p falls outside interval %p-%p", //
addr, addr + addrsize, //
elf, (char *)elf + mapsize); //
abort();
}
#endif
}

View file

@ -187,11 +187,13 @@
#define R_PPC_ADDR32 1
#define R_PPC_ADDR24 2
#define R_PPC_ADDR16 3
#define R_PPC_REL32 26
#define R_PPC64_NONE R_PPC_NONE
#define R_PPC64_ADDR32 R_PPC_ADDR32
#define R_PPC64_ADDR24 R_PPC_ADDR24
#define R_PPC64_ADDR16 R_PPC_ADDR16
#define R_PPC64_REL32 R_PPC_REL32
#define R_RISCV_NONE 0
#define R_RISCV_32 1

View file

@ -17,9 +17,8 @@ char *GetElfStringTable(const Elf64_Ehdr *, size_t);
char *GetElfStrs(const Elf64_Ehdr *, size_t, size_t *);
Elf64_Sym *GetElfSymbolTable(const Elf64_Ehdr *, size_t, Elf64_Xword *);
bool IsElf64Binary(const Elf64_Ehdr *, size_t);
void CheckElfAddress(const Elf64_Ehdr *, size_t, intptr_t, size_t);
bool IsElfSymbolContent(const Elf64_Sym *);
Elf64_Phdr *GetElfSegmentHeaderAddress(const Elf64_Ehdr *, size_t, unsigned);
Elf64_Phdr *GetElfSegmentHeaderAddress(const Elf64_Ehdr *, size_t, Elf64_Half);
Elf64_Shdr *GetElfSectionHeaderAddress(const Elf64_Ehdr *, size_t, Elf64_Half);
void *GetElfSectionAddress(const Elf64_Ehdr *, size_t, const Elf64_Shdr *);
char *GetElfSectionNameStringTable(const Elf64_Ehdr *, size_t);

View file

@ -21,20 +21,16 @@
#include "libc/str/str.h"
char *GetElfDynStringTable(const Elf64_Ehdr *elf, size_t mapsize) {
int i;
char *name;
Elf64_Half i;
Elf64_Shdr *shdr;
if (elf->e_shentsize) {
for (i = 0; i < elf->e_shnum; ++i) {
shdr = GetElfSectionHeaderAddress(elf, mapsize, i);
if (shdr->sh_type == SHT_STRTAB) {
name = GetElfSectionName(elf, mapsize,
GetElfSectionHeaderAddress(elf, mapsize, i));
if (name && !strcmp(name, ".dynstr")) {
return GetElfSectionAddress(elf, mapsize, shdr);
}
}
for (i = 0; i < elf->e_shnum; ++i) {
if ((shdr = GetElfSectionHeaderAddress(elf, mapsize, i)) &&
shdr->sh_type == SHT_STRTAB &&
(name = GetElfSectionName(elf, mapsize, shdr)) &&
!strcmp(name, ".dynstr")) {
return GetElfSectionAddress(elf, mapsize, shdr);
}
}
return NULL;
return 0;
}

View file

@ -21,17 +21,15 @@
Elf64_Sym *GetElfDynSymbolTable(const Elf64_Ehdr *elf, size_t mapsize,
Elf64_Xword *out_count) {
Elf64_Half i;
int i;
Elf64_Shdr *shdr;
if (elf->e_shentsize) {
for (i = elf->e_shnum; i > 0; --i) {
shdr = GetElfSectionHeaderAddress(elf, mapsize, i - 1);
if (shdr->sh_type == SHT_DYNSYM) {
if (shdr->sh_entsize != sizeof(Elf64_Sym)) continue;
if (out_count) *out_count = shdr->sh_size / shdr->sh_entsize;
return GetElfSectionAddress(elf, mapsize, shdr);
}
for (i = elf->e_shnum; i-- > 0;) {
if ((shdr = GetElfSectionHeaderAddress(elf, mapsize, i)) && //
shdr->sh_type == SHT_DYNSYM && //
shdr->sh_entsize == sizeof(Elf64_Sym)) {
if (out_count) *out_count = shdr->sh_size / sizeof(Elf64_Sym);
return GetElfSectionAddress(elf, mapsize, shdr);
}
}
return NULL;
return 0;
}

View file

@ -17,12 +17,16 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/elf/elf.h"
#include "libc/stdckdint.h"
void *GetElfSectionAddress(const Elf64_Ehdr *elf, size_t mapsize,
const Elf64_Shdr *shdr) {
intptr_t addr, size;
addr = (intptr_t)elf + (intptr_t)shdr->sh_offset;
size = (intptr_t)shdr->sh_size;
CheckElfAddress(elf, mapsize, addr, size);
// note: should not be used on bss section
void *GetElfSectionAddress(const Elf64_Ehdr *elf, // validated
size_t mapsize, // validated
const Elf64_Shdr *shdr) { // foreign
uint64_t addr, last;
if (!shdr) return 0;
if (ckd_add(&addr, (uintptr_t)elf, shdr->sh_offset)) return 0;
if (ckd_add(&last, addr, shdr->sh_size)) return 0;
if (last > (uintptr_t)elf + mapsize) return 0;
return (void *)addr;
}

View file

@ -17,11 +17,16 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/elf/elf.h"
#include "libc/stdckdint.h"
Elf64_Shdr *GetElfSectionHeaderAddress(const Elf64_Ehdr *elf, size_t mapsize,
Elf64_Half i) {
intptr_t addr =
((intptr_t)elf + (intptr_t)elf->e_shoff + (intptr_t)elf->e_shentsize * i);
CheckElfAddress(elf, mapsize, addr, elf->e_shentsize);
Elf64_Shdr *GetElfSectionHeaderAddress(const Elf64_Ehdr *elf, //
size_t mapsize, //
Elf64_Half i) { //
uint64_t addr, last;
if (i >= elf->e_shnum) return 0;
if (ckd_add(&addr, (uintptr_t)elf, elf->e_shoff)) return 0;
if (ckd_add(&addr, addr, (unsigned)i * elf->e_shentsize)) return 0;
if (ckd_add(&last, addr, elf->e_shentsize)) return 0;
if (last > (uintptr_t)elf + mapsize) return 0;
return (Elf64_Shdr *)addr;
}

View file

@ -20,7 +20,7 @@
const char *GetElfSectionName(const Elf64_Ehdr *elf, size_t mapsize,
Elf64_Shdr *shdr) {
if (!elf || !shdr) return NULL;
if (!shdr) return 0;
return GetElfString(elf, mapsize, GetElfSectionNameStringTable(elf, mapsize),
shdr->sh_name);
}

View file

@ -19,7 +19,7 @@
#include "libc/elf/elf.h"
char *GetElfSectionNameStringTable(const Elf64_Ehdr *elf, size_t mapsize) {
if (!elf->e_shoff || !elf->e_shentsize) return NULL;
if (!elf->e_shoff || !elf->e_shentsize) return 0;
return GetElfSectionAddress(
elf, mapsize, GetElfSectionHeaderAddress(elf, mapsize, elf->e_shstrndx));
}

View file

@ -17,11 +17,16 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/elf/elf.h"
#include "libc/stdckdint.h"
Elf64_Phdr *GetElfSegmentHeaderAddress(const Elf64_Ehdr *elf, size_t mapsize,
unsigned i) {
intptr_t addr =
((intptr_t)elf + (intptr_t)elf->e_phoff + (intptr_t)elf->e_phentsize * i);
CheckElfAddress(elf, mapsize, addr, elf->e_phentsize);
Elf64_Phdr *GetElfSegmentHeaderAddress(const Elf64_Ehdr *elf, //
size_t mapsize, //
Elf64_Half i) { //
uint64_t last, addr;
if (i >= elf->e_phnum) return 0;
if (ckd_add(&addr, (uintptr_t)elf, elf->e_phoff)) return 0;
if (ckd_add(&addr, addr, (unsigned)i * elf->e_phentsize)) return 0;
if (ckd_add(&last, addr, elf->e_phentsize)) return 0;
if (last > (uintptr_t)elf + mapsize) return 0;
return (Elf64_Phdr *)addr;
}

View file

@ -17,15 +17,17 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/elf/elf.h"
#include "libc/stdckdint.h"
#include "libc/str/str.h"
char *GetElfString(const Elf64_Ehdr *elf, size_t mapsize, const char *strtab,
Elf64_Word rva) {
intptr_t addr = (intptr_t)strtab + rva;
#if !(TRUSTWORTHY + ELF_TRUSTWORTHY + 0)
CheckElfAddress(elf, mapsize, addr, 0);
CheckElfAddress(elf, mapsize, addr,
strnlen((char *)addr, (intptr_t)elf + mapsize - addr) + 1);
#endif
char *GetElfString(const Elf64_Ehdr *elf, // validated
size_t mapsize, // validated
const char *strtab, // validated
Elf64_Word rva) { // foreign
uintptr_t addr;
if (!strtab) return 0;
if (ckd_add(&addr, (uintptr_t)strtab, rva)) return 0;
if (addr >= (uintptr_t)elf + mapsize) return 0;
if (!memchr((char *)addr, 0, (uintptr_t)elf + mapsize - addr)) return 0;
return (char *)addr;
}

View file

@ -21,19 +21,15 @@
#include "libc/str/str.h"
char *GetElfStringTable(const Elf64_Ehdr *elf, size_t mapsize) {
int i;
char *name;
Elf64_Half i;
Elf64_Shdr *shdr;
if (elf->e_shentsize) {
for (i = 0; i < elf->e_shnum; ++i) {
shdr = GetElfSectionHeaderAddress(elf, mapsize, i);
if (shdr->sh_type == SHT_STRTAB) {
name = GetElfSectionName(elf, mapsize,
GetElfSectionHeaderAddress(elf, mapsize, i));
if (name && !strcmp(name, ".strtab")) {
return GetElfSectionAddress(elf, mapsize, shdr);
}
}
for (i = 0; i < elf->e_shnum; ++i) {
if ((shdr = GetElfSectionHeaderAddress(elf, mapsize, i)) &&
shdr->sh_type == SHT_STRTAB &&
(name = GetElfSectionName(elf, mapsize, shdr)) &&
!strcmp(name, ".strtab")) {
return GetElfSectionAddress(elf, mapsize, shdr);
}
}
return NULL;

View file

@ -21,18 +21,16 @@
#include "libc/str/str.h"
char *GetElfStrs(const Elf64_Ehdr *elf, size_t mapsize, size_t *out_size) {
int i;
char *name;
Elf64_Half i;
Elf64_Shdr *shdr;
for (i = 0; i < elf->e_shnum; ++i) {
shdr = GetElfSectionHeaderAddress(elf, mapsize, i);
if (shdr->sh_type == SHT_STRTAB) {
name = GetElfSectionName(elf, mapsize,
GetElfSectionHeaderAddress(elf, mapsize, i));
if (name && !strcmp(name, ".strtab")) {
if (out_size) *out_size = shdr->sh_size;
return GetElfSectionAddress(elf, mapsize, shdr);
}
if ((shdr = GetElfSectionHeaderAddress(elf, mapsize, i)) &&
shdr->sh_type == SHT_STRTAB &&
(name = GetElfSectionName(elf, mapsize, shdr)) &&
!strcmp(name, ".strtab")) {
if (out_size) *out_size = shdr->sh_size;
return GetElfSectionAddress(elf, mapsize, shdr);
}
}
return 0;

View file

@ -21,14 +21,14 @@
Elf64_Sym *GetElfSymbolTable(const Elf64_Ehdr *elf, size_t mapsize,
Elf64_Xword *out_count) {
Elf64_Half i;
int i;
Elf64_Shdr *shdr;
if (elf->e_shentsize) {
for (i = elf->e_shnum; i > 0; --i) {
shdr = GetElfSectionHeaderAddress(elf, mapsize, i - 1);
if (shdr->sh_type == SHT_SYMTAB) {
if (shdr->sh_entsize != sizeof(Elf64_Sym)) continue;
if (out_count) *out_count = shdr->sh_size / shdr->sh_entsize;
if (shdr->sh_entsize != sizeof(Elf64_Sym)) __builtin_trap();
if (out_count) *out_count = shdr->sh_size / sizeof(Elf64_Sym);
return GetElfSectionAddress(elf, mapsize, shdr);
}
}

View file

@ -2,10 +2,11 @@
#define COSMOPOLITAN_LIBC_ELF_STRUCT_EHDR_H_
#include "libc/elf/def.h"
#include "libc/elf/scalar.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#define EI_NIDENT 16
#if !(__ASSEMBLER__ + __LINKER__ + 0)
typedef struct Elf64_Ehdr {
unsigned char e_ident[EI_NIDENT];
Elf64_Half e_type;

View file

@ -16,14 +16,14 @@ COSMOPOLITAN_C_START_
#define GetSectionName(e, s) GetStr(GetShstrtab(e), (s)->sh_name)
#define GetPhdr(e, i) \
((Elf64_Phdr *)((intptr_t)(e) + (e)->e_phoff + \
(size_t)(e)->e_phentsize * (i)))
(unsigned)(e)->e_phentsize * (i)))
#define GetShdr(e, i) \
((Elf64_Shdr *)((intptr_t)(e) + (e)->e_shoff + \
(size_t)(e)->e_shentsize * (i)))
(unsigned)(e)->e_shentsize * (i)))
static inline char *GetStrtab(Elf64_Ehdr *e, size_t *n) {
int i;
char *name;
Elf64_Half i;
Elf64_Shdr *shdr;
for (i = 0; i < e->e_shnum; ++i) {
shdr = GetShdr(e, i);
@ -39,13 +39,12 @@ static inline char *GetStrtab(Elf64_Ehdr *e, size_t *n) {
}
static inline Elf64_Sym *GetSymtab(Elf64_Ehdr *e, Elf64_Xword *n) {
Elf64_Half i;
int i;
Elf64_Shdr *shdr;
for (i = e->e_shnum; i > 0; --i) {
shdr = GetShdr(e, i - 1);
for (i = e->e_shnum; i-- > 0;) {
shdr = GetShdr(e, i);
if (shdr->sh_type == SHT_SYMTAB) {
if (shdr->sh_entsize != sizeof(Elf64_Sym)) continue;
if (n) *n = shdr->sh_size / shdr->sh_entsize;
if (n) *n = shdr->sh_size / sizeof(Elf64_Sym);
return GetSection(e, shdr);
}
}

View file

@ -19,6 +19,7 @@
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/limits.h"
#include "libc/stdckdint.h"
#include "libc/str/str.h"
/**
@ -46,8 +47,7 @@ int atoi(const char *s) {
d = c == '-' ? -1 : 1;
if (c == '-' || c == '+') c = *s++;
for (x = 0; isdigit(c); c = *s++) {
if (__builtin_mul_overflow(x, 10, &x) ||
__builtin_add_overflow(x, (c - '0') * d, &x)) {
if (ckd_mul(&x, x, 10) || ckd_add(&x, x, (c - '0') * d)) {
errno = ERANGE;
if (d > 0) {
return INT_MAX;

View file

@ -19,6 +19,7 @@
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/limits.h"
#include "libc/stdckdint.h"
#include "libc/str/str.h"
/**
@ -36,8 +37,7 @@ long atol(const char *s) {
d = c == '-' ? -1 : 1;
if (c == '-' || c == '+') c = *s++;
for (x = 0; isdigit(c); c = *s++) {
if (__builtin_mul_overflow(x, 10, &x) ||
__builtin_add_overflow(x, (c - '0') * d, &x)) {
if (ckd_mul(&x, x, 10) || ckd_add(&x, x, (c - '0') * d)) {
errno = ERANGE;
if (d > 0) {
return LONG_MAX;

View file

@ -18,6 +18,7 @@
*/
#include "libc/fmt/conv.h"
#include "libc/fmt/fmt.h"
#include "libc/stdckdint.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
@ -89,8 +90,7 @@ long sizetol(const char *s, long b) {
}
x = 0;
do {
if (__builtin_mul_overflow(x, 10, &x) ||
__builtin_add_overflow(x, (c - '0') * d, &x)) {
if (ckd_mul(&x, x, 10) || ckd_add(&x, x, (c - '0') * d)) {
return eoverflow();
}
} while (isdigit((c = *s++)));
@ -98,7 +98,7 @@ long sizetol(const char *s, long b) {
return einval();
}
while (e--) {
if (__builtin_mul_overflow(x, b, &x)) {
if (ckd_mul(&x, x, b)) {
return eoverflow();
}
}

View file

@ -20,6 +20,7 @@
#include "libc/fmt/conv.h"
#include "libc/fmt/strtol.internal.h"
#include "libc/limits.h"
#include "libc/stdckdint.h"
#include "libc/str/str.h"
#include "libc/str/tab.internal.h"
@ -47,8 +48,7 @@ int128_t strtoi128(const char *s, char **endptr, int base) {
if ((c = kBase36[c & 255]) && --c < base) {
if (!((t |= 1) & 2)) {
do {
if (__builtin_mul_overflow(x, base, &x) ||
__builtin_add_overflow(x, c * d, &x)) {
if (ckd_mul(&x, x, base) || ckd_add(&x, x, c * d)) {
x = d > 0 ? INT128_MAX : INT128_MIN;
errno = ERANGE;
t |= 2;

View file

@ -20,6 +20,7 @@
#include "libc/fmt/conv.h"
#include "libc/fmt/strtol.internal.h"
#include "libc/limits.h"
#include "libc/stdckdint.h"
#include "libc/str/str.h"
#include "libc/str/tab.internal.h"
@ -58,8 +59,7 @@ long strtol(const char *s, char **endptr, int base) {
if ((c = kBase36[c & 255]) && --c < base) {
if (!((t |= 1) & 2)) {
do {
if (__builtin_mul_overflow(x, base, &x) ||
__builtin_add_overflow(x, c * d, &x)) {
if (ckd_mul(&x, x, base) || ckd_add(&x, x, c * d)) {
x = d > 0 ? LONG_MAX : LONG_MIN;
errno = ERANGE;
t |= 2;

View file

@ -20,6 +20,7 @@
#include "libc/fmt/conv.h"
#include "libc/fmt/strtol.internal.h"
#include "libc/limits.h"
#include "libc/stdckdint.h"
#include "libc/str/str.h"
#include "libc/str/tab.internal.h"
@ -47,8 +48,7 @@ unsigned long strtoul(const char *s, char **endptr, int base) {
if ((c = kBase36[c & 255]) && --c < base) {
t |= 1;
do {
if (__builtin_mul_overflow(x, base, &x) ||
__builtin_add_overflow(x, c, &x)) {
if (ckd_mul(&x, x, base) || ckd_add(&x, x, c)) {
if (endptr) *endptr = s + 1;
errno = ERANGE;
return ULONG_MAX;

View file

@ -20,6 +20,7 @@
#include "libc/fmt/conv.h"
#include "libc/fmt/strtol.internal.h"
#include "libc/limits.h"
#include "libc/stdckdint.h"
#include "libc/str/str.h"
#include "libc/str/tab.internal.h"
@ -47,8 +48,7 @@ int128_t wcstoi128(const wchar_t *s, wchar_t **endptr, int base) {
if ((c = kBase36[c & 255]) && --c < base) {
if (!((t |= 1) & 2)) {
do {
if (__builtin_mul_overflow(x, base, &x) ||
__builtin_add_overflow(x, c * d, &x)) {
if (ckd_mul(&x, x, base) || ckd_add(&x, x, c * d)) {
x = d > 0 ? INT128_MAX : INT128_MIN;
errno = ERANGE;
t |= 2;

View file

@ -20,6 +20,7 @@
#include "libc/fmt/conv.h"
#include "libc/fmt/strtol.internal.h"
#include "libc/limits.h"
#include "libc/stdckdint.h"
#include "libc/str/str.h"
#include "libc/str/tab.internal.h"
@ -46,8 +47,7 @@ long wcstol(const wchar_t *s, wchar_t **endptr, int base) {
if ((c = kBase36[c & 255]) && --c < base) {
if (!((t |= 1) & 2)) {
do {
if (__builtin_mul_overflow(x, base, &x) ||
__builtin_add_overflow(x, c * d, &x)) {
if (ckd_mul(&x, x, base) || ckd_add(&x, x, c * d)) {
x = d > 0 ? LONG_MAX : LONG_MIN;
errno = ERANGE;
t |= 2;

View file

@ -20,6 +20,7 @@
#include "libc/fmt/conv.h"
#include "libc/fmt/strtol.internal.h"
#include "libc/limits.h"
#include "libc/stdckdint.h"
#include "libc/str/str.h"
#include "libc/str/tab.internal.h"
@ -46,8 +47,7 @@ unsigned long wcstoul(const wchar_t *s, wchar_t **endptr, int base) {
if ((c = kBase36[c & 255]) && --c < base) {
t |= 1;
do {
if (__builtin_mul_overflow(x, base, &x) ||
__builtin_add_overflow(x, c, &x)) {
if (ckd_mul(&x, x, base) || ckd_add(&x, x, c)) {
if (endptr) *endptr = s + 1;
errno = ERANGE;
return ULONG_MAX;

View file

@ -41,6 +41,7 @@
#include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.internal.h"
#include "libc/stdckdint.h"
#include "libc/str/tab.internal.h"
#include "libc/sysv/consts/auxv.h"
#include "libc/sysv/consts/map.h"
@ -594,8 +595,7 @@ bool __asan_is_valid_strlist(char *const *p) {
bool __asan_is_valid_iov(const struct iovec *iov, int iovlen) {
int i;
size_t size;
if (iovlen >= 0 &&
!__builtin_mul_overflow(iovlen, sizeof(struct iovec), &size) &&
if (iovlen >= 0 && !ckd_mul(&size, iovlen, sizeof(struct iovec)) &&
__asan_is_valid(iov, size)) {
for (i = 0; i < iovlen; ++i) {
if (!__asan_is_valid(iov[i].iov_base, iov[i].iov_len)) {
@ -1067,7 +1067,7 @@ static struct AsanExtra *__asan_get_extra(const void *p, size_t *c) {
struct AsanExtra *e;
f = (intptr_t)p >> 16;
if (!kisdangerous(p) && (n = _weaken(dlmalloc_usable_size)(p)) > sizeof(*e) &&
!__builtin_add_overflow((intptr_t)p, n, &x) && x <= 0x800000000000 &&
!ckd_add(&x, (intptr_t)p, n) && x <= 0x800000000000 &&
(LIKELY(f == (int)((x - 1) >> 16)) || !kisdangerous((void *)(x - 1))) &&
(LIKELY(f == (int)((x = x - sizeof(*e)) >> 16)) ||
__asan_is_mapped(x >> 16)) &&
@ -1237,7 +1237,7 @@ void *__asan_calloc(size_t n, size_t m) {
char *p;
struct AsanTrace bt;
__asan_trace(&bt, RBP);
if (__builtin_mul_overflow(n, m, &n)) n = -1;
if (ckd_mul(&n, n, m)) n = -1;
return __asan_allocate(16, n, &bt, kAsanHeapUnderrun, kAsanHeapOverrun, 0x00);
}

View file

@ -1,3 +1,21 @@
/*-*- 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 2023 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/runtime/fenv.h"
/**

View file

@ -18,6 +18,7 @@
*/
#include "libc/limits.h"
#include "libc/runtime/internal.h"
#include "libc/stdckdint.h"
/**
* Returns -𝑥, aborting on overflow.
@ -66,7 +67,7 @@ int128_t __negvti2(int128_t x) {
*/
int __addvsi3(int x, int y) {
int z;
if (__builtin_add_overflow(x, y, &z)) {
if (ckd_add(&z, x, y)) {
__on_arithmetic_overflow();
}
return z;
@ -80,7 +81,7 @@ int __addvsi3(int x, int y) {
*/
long __addvdi3(long x, long y) {
long z;
if (__builtin_add_overflow(x, y, &z)) {
if (ckd_add(&z, x, y)) {
__on_arithmetic_overflow();
}
return z;
@ -94,7 +95,7 @@ long __addvdi3(long x, long y) {
*/
int128_t __addvti3(int128_t x, int128_t y) {
int128_t z;
if (__builtin_add_overflow(x, y, &z)) {
if (ckd_add(&z, x, y)) {
__on_arithmetic_overflow();
}
return z;
@ -108,7 +109,7 @@ int128_t __addvti3(int128_t x, int128_t y) {
*/
int __subvsi3(int x, int y) {
int z;
if (__builtin_sub_overflow(x, y, &z)) {
if (ckd_sub(&z, x, y)) {
__on_arithmetic_overflow();
}
return z;
@ -122,7 +123,7 @@ int __subvsi3(int x, int y) {
*/
long __subvdi3(long x, long y) {
long z;
if (__builtin_sub_overflow(x, y, &z)) {
if (ckd_sub(&z, x, y)) {
__on_arithmetic_overflow();
}
return z;
@ -136,7 +137,7 @@ long __subvdi3(long x, long y) {
*/
int128_t __subvti3(int128_t x, int128_t y) {
int128_t z;
if (__builtin_sub_overflow(x, y, &z)) {
if (ckd_sub(&z, x, y)) {
__on_arithmetic_overflow();
}
return z;
@ -150,7 +151,7 @@ int128_t __subvti3(int128_t x, int128_t y) {
*/
int __mulvsi3(int x, int y) {
int z;
if (__builtin_mul_overflow(x, y, &z)) {
if (ckd_mul(&z, x, y)) {
__on_arithmetic_overflow();
}
return z;
@ -164,7 +165,7 @@ int __mulvsi3(int x, int y) {
*/
long __mulvdi3(long x, long y) {
long z;
if (__builtin_mul_overflow(x, y, &z)) {
if (ckd_mul(&z, x, y)) {
__on_arithmetic_overflow();
}
return z;
@ -178,7 +179,7 @@ long __mulvdi3(long x, long y) {
*/
int128_t __mulvti3(int128_t x, int128_t y) {
int128_t z;
if (__builtin_mul_overflow(x, y, &z)) {
if (ckd_mul(&z, x, y)) {
__on_arithmetic_overflow();
}
return z;

View file

@ -51,6 +51,7 @@
#include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h"
#include "libc/runtime/symbols.internal.h"
#include "libc/stdckdint.h"
#include "libc/str/str.h"
#include "libc/str/tab.internal.h"
#include "libc/str/utf16.h"
@ -108,7 +109,7 @@ extern _Hide struct SymbolTable *__symtab;
privileged static inline char *kadvance(char *p, char *e, long n) {
intptr_t t = (intptr_t)p;
if (__builtin_add_overflow(t, n, &t)) t = (intptr_t)e;
if (ckd_add(&t, t, n)) t = (intptr_t)e;
return (char *)t;
}

View file

@ -73,12 +73,8 @@ noasan static inline const unsigned char *memchr_sse(const unsigned char *s,
void *memchr(const void *s, int c, size_t n) {
#ifdef __x86_64__
const void *r;
if (!IsTiny() && X86_HAVE(SSE)) {
if (IsAsan()) __asan_verify(s, n);
r = memchr_sse(s, c, n);
} else {
r = memchr_pure(s, c, n);
}
if (IsAsan()) __asan_verify(s, n);
r = memchr_sse(s, c, n);
return (void *)r;
#else
return memchr_pure(s, c, n);

View file

@ -71,12 +71,8 @@ noasan static inline const unsigned char *memrchr_sse(const unsigned char *s,
void *memrchr(const void *s, int c, size_t n) {
#ifdef __x86_64__
const void *r;
if (!IsTiny() && X86_HAVE(SSE)) {
if (IsAsan()) __asan_verify(s, n);
r = memrchr_sse(s, c, n);
} else {
r = memrchr_pure(s, c, n);
}
if (IsAsan()) __asan_verify(s, n);
r = memrchr_sse(s, c, n);
return (void *)r;
#else
return memrchr_pure(s, c, n);

4
libc/isystem/stdckdint.h Normal file
View file

@ -0,0 +1,4 @@
#ifndef COSMOPOLITAN_LIBC_ISYSTEM_STDCKDINT_H_
#define COSMOPOLITAN_LIBC_ISYSTEM_STDCKDINT_H_
#include "libc/stdckdint.h"
#endif /* COSMOPOLITAN_LIBC_ISYSTEM_STDCKDINT_H_ */

View file

@ -24,6 +24,7 @@
#include "libc/macros.internal.h"
#include "libc/mem/alg.h"
#include "libc/runtime/runtime.h"
#include "libc/stdckdint.h"
#include "libc/stdio/stdio.h"
#ifdef __x86_64__
@ -32,7 +33,7 @@ static long GetLongSum(const long *h, size_t n) {
long t;
size_t i;
for (t = i = 0; i < n; ++i) {
if (__builtin_add_overflow(t, h[i], &t)) {
if (ckd_add(&t, t, h[i])) {
t = LONG_MAX;
break;
}

View file

@ -30,6 +30,7 @@
#include "libc/mem/hook.internal.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/stdckdint.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
@ -151,7 +152,7 @@ static void *__arena_malloc(size_t n) {
static void *__arena_calloc(size_t n, size_t z) {
__arena_check();
if (__builtin_mul_overflow(n, z, &n)) n = -1;
if (ckd_mul(&n, n, z)) n = -1;
return __arena_alloc(16, n);
}

View file

@ -19,6 +19,7 @@
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/mem/mem.h"
#include "libc/stdckdint.h"
/**
* Manages array memory, the BSD way.
@ -30,7 +31,7 @@
*/
void *reallocarray(void *ptr, size_t nmemb, size_t itemsize) {
size_t n;
if (!__builtin_mul_overflow(nmemb, itemsize, &n)) {
if (!ckd_mul(&n, nmemb, itemsize)) {
return realloc(ptr, n);
} else {
errno = ENOMEM;

View file

@ -19,31 +19,28 @@
#include "libc/macros.internal.h"
#include "ape/relocations.h"
#include "libc/zip.internal.h"
.section .zip.eocd,"",@progbits
// ZIP Central Directory.
.section .zip.3,"",@progbits
.hidden __zip_start
// ZIP End Of Central Directory (EOCD) record.
.globl __zip_start
.type __zip_start,@object
__zip_start:
.previous/*
...
decentralized content
...
*/.section .zip.5,"",@progbits
__zip_end:
.long kZipCdirHdrMagic // magic
__zip_eocd: // let symbol be discarded
.long kZipCdirHdrMagicTodo // magic (scan backwards for this)
.short 0 // disk
.short 0 // starting disk
.short v_zip_records // number of records on disk
.short v_zip_records // records
.long v_zip_cdirsize // size of central directory
.long v_zip_cdoffset // central directory offset
.short v_zip_commentsize // comment size
.endobj __zip_end,globl,hidden
.previous
.short 0 // number of records on disk
.short 0 // records
.endobj __zip_eocd,globl
.weak v_zip_records
.weak v_zip_cdirsize
.weak v_zip_cdoffset
.weak v_zip_commentsize
__zip_eocd.size:
.weak __zip_cdir_size
.long __zip_cdir_size
.endobj __zip_eocd.size
__zip_eocd.offset:
.long 0
.endobj __zip_eocd.offset
__zip_eocd.commentsize:
.short 0
.endobj __zip_eocd.commentsize

View file

@ -23,6 +23,7 @@
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/stdckdint.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
@ -48,8 +49,7 @@ bool __grow(void *pp, size_t *capacity, size_t itemsize, size_t extra) {
p2 = NULL;
n1 = *capacity;
n2 = (*p ? n1 + (n1 >> 1) : MAX(4, INITIAL_CAPACITY / itemsize)) + extra;
if (!__builtin_mul_overflow(n1, itemsize, &t1) &&
!__builtin_mul_overflow(n2, itemsize, &t2)) {
if (!ckd_mul(&t1, n1, itemsize) && !ckd_mul(&t2, n2, itemsize)) {
if (_weaken(realloc) && (p2 = _weaken(realloc)(p1, ROUNDUP(t2, 32)))) {
if (!p1 && *p) memcpy(p2, *p, t1);
bzero((char *)p2 + t1, t2 - t1);

View file

@ -43,6 +43,7 @@
#include "libc/runtime/internal.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/stdckdint.h"
#include "libc/stdio/rand.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/map.h"
@ -99,9 +100,9 @@ static noasan bool ChooseMemoryInterval(int x, int n, int align, int *res) {
if (i < _mmi.i) {
// check to see if there's space available before the first entry
if (!__builtin_add_overflow(x, align - 1, &start)) {
if (!ckd_add(&start, x, align - 1)) {
start &= -align;
if (!__builtin_add_overflow(start, n - 1, &end)) {
if (!ckd_add(&end, start, n - 1)) {
if (end < _mmi.p[i].x) {
*res = start;
return true;
@ -111,10 +112,10 @@ static noasan bool ChooseMemoryInterval(int x, int n, int align, int *res) {
// check to see if there's space available between two entries
while (++i < _mmi.i) {
if (!__builtin_add_overflow(_mmi.p[i - 1].y, 1, &start) &&
!__builtin_add_overflow(start, align - 1, &start)) {
if (!ckd_add(&start, _mmi.p[i - 1].y, 1) &&
!ckd_add(&start, start, align - 1)) {
start &= -align;
if (!__builtin_add_overflow(start, n - 1, &end)) {
if (!ckd_add(&end, start, n - 1)) {
if (end < _mmi.p[i].x) {
*res = start;
return true;
@ -125,10 +126,10 @@ static noasan bool ChooseMemoryInterval(int x, int n, int align, int *res) {
}
// otherwise append after the last entry if space is available
if (!__builtin_add_overflow(_mmi.p[i - 1].y, 1, &start) &&
!__builtin_add_overflow(start, align - 1, &start)) {
if (!ckd_add(&start, _mmi.p[i - 1].y, 1) &&
!ckd_add(&start, start, align - 1)) {
start &= -align;
if (!__builtin_add_overflow(start, n - 1, &end)) {
if (!ckd_add(&end, start, n - 1)) {
*res = start;
return true;
}
@ -137,9 +138,9 @@ static noasan bool ChooseMemoryInterval(int x, int n, int align, int *res) {
} else {
// if memtrack is empty, then just assign the requested address
// assuming it doesn't overflow
if (!__builtin_add_overflow(x, align - 1, &start)) {
if (!ckd_add(&start, x, align - 1)) {
start &= -align;
if (!__builtin_add_overflow(start, n - 1, &end)) {
if (!ckd_add(&end, start, n - 1)) {
*res = start;
return true;
}
@ -293,8 +294,7 @@ noasan inline void *_Mmap(void *addr, size_t size, int prot, int flags, int fd,
}
if (__virtualmax < LONG_MAX &&
(__builtin_add_overflow((virtualused = GetMemtrackSize(&_mmi)), size,
&virtualneed) ||
(ckd_add(&virtualneed, (virtualused = GetMemtrackSize(&_mmi)), size) ||
virtualneed > __virtualmax)) {
STRACE("mmap %'zu size + %'zu inuse exceeds virtual memory limit %'zu",
size, virtualused, __virtualmax);
@ -308,8 +308,7 @@ noasan inline void *_Mmap(void *addr, size_t size, int prot, int flags, int fd,
return VIP(eexist());
}
if (__builtin_add_overflow((int)(size >> 16), (int)!!(size & (FRAMESIZE - 1)),
&n)) {
if (ckd_add(&n, (int)(size >> 16), (int)!!(size & (FRAMESIZE - 1)))) {
STRACE("mmap range overflows");
return VIP(einval());
}

View file

@ -24,6 +24,7 @@
#include "libc/sock/sock.h"
#include "libc/sock/struct/pollfd.h"
#include "libc/sock/struct/pollfd.internal.h"
#include "libc/stdckdint.h"
#include "libc/sysv/consts/poll.h"
#include "libc/sysv/errfuns.h"
@ -55,8 +56,7 @@ int sys_select_nt(int nfds, fd_set *readfds, fd_set *writefds,
}
// convert the wait time to a word
if (!timeout || __builtin_add_overflow(timeout->tv_sec,
timeout->tv_usec / 1000, &millis)) {
if (!timeout || ckd_add(&millis, timeout->tv_sec, timeout->tv_usec / 1000)) {
millis = -1;
}

View file

@ -23,6 +23,7 @@
#include "libc/sock/internal.h"
#include "libc/sock/struct/linger.h"
#include "libc/sock/syscall_fd.internal.h"
#include "libc/stdckdint.h"
#include "libc/sysv/consts/so.h"
#include "libc/sysv/consts/sol.h"
#include "libc/sysv/errfuns.h"
@ -48,9 +49,9 @@ textwindows int sys_setsockopt_nt(struct Fd *fd, int level, int optname,
} else if ((optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) && optval &&
optlen == sizeof(struct timeval)) {
tv = optval;
if (__builtin_mul_overflow(tv->tv_sec, 1000, &ms) ||
__builtin_add_overflow(tv->tv_usec, 999, &micros) ||
__builtin_add_overflow(ms, micros / 1000, &ms) ||
if (ckd_mul(&ms, tv->tv_sec, 1000) || //
ckd_add(&micros, tv->tv_usec, 999) || //
ckd_add(&ms, ms, micros / 1000) || //
(ms < 0 || ms > 0xffffffff)) {
u.millis = 0xffffffff;
} else {

8
libc/stdckdint.h Normal file
View file

@ -0,0 +1,8 @@
#ifndef COSMOPOLITAN_LIBC_STDCKDINT_H_
#define COSMOPOLITAN_LIBC_STDCKDINT_H_
#define ckd_add(R, A, B) __builtin_add_overflow((A), (B), (R))
#define ckd_sub(R, A, B) __builtin_sub_overflow((A), (B), (R))
#define ckd_mul(R, A, B) __builtin_mul_overflow((A), (B), (R))
#endif /* COSMOPOLITAN_LIBC_STDCKDINT_H_ */

View file

@ -23,6 +23,7 @@
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/sock.h"
#include "libc/stdckdint.h"
#include "libc/stdio/internal.h"
#include "libc/stdio/stdio.h"
#include "libc/str/internal.h"
@ -53,7 +54,7 @@ size_t fread_unlocked(void *buf, size_t stride, size_t count, FILE *f) {
f->state = errno = EINVAL;
return 0;
}
if (__builtin_mul_overflow(stride, count, &n)) {
if (ckd_mul(&n, stride, count)) {
f->state = errno = EOVERFLOW;
return 0;
}

View file

@ -26,6 +26,7 @@
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/sock.h"
#include "libc/stdckdint.h"
#include "libc/stdio/internal.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
@ -51,7 +52,7 @@ size_t fwrite_unlocked(const void *data, size_t stride, size_t count, FILE *f) {
f->state = errno = EBADF;
return 0;
}
if (__builtin_mul_overflow(stride, count, &n)) {
if (ckd_mul(&n, stride, count)) {
f->state = errno = EOVERFLOW;
return 0;
}

View file

@ -20,6 +20,7 @@
#include "libc/intrin/asan.internal.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/runtime/runtime.h"
#include "libc/stdckdint.h"
void djbsort_avx2(int32_t *, long);
@ -29,7 +30,7 @@ void djbsort_avx2(int32_t *, long);
void djbsort(int32_t *a, size_t n) {
size_t m;
if (IsAsan()) {
if (__builtin_mul_overflow(n, 4, &m)) m = -1;
if (ckd_mul(&m, n, 4)) m = -1;
__asan_verify(a, m);
}
if (n > 1) {

View file

@ -32,16 +32,18 @@ typedef long long v2di __attribute__((__vector_size__(16), __aligned__(1)));
* caller needs to check the first four bytes of the returned value to
* determine whether to use ZIP_CDIR_xxx() or ZIP_CDIR64_xxx() macros.
*
* @param p points to file memory
* @param f points to file memory
* @param n is byte size of file
* @param e may receive error code when null is returned
* @return pointer to EOCD64 or EOCD, otherwise null
*/
void *GetZipEocd(const uint8_t *p, size_t n, int *e) {
void *GetZipEocd(const void *f, size_t n, int *e) {
v2di x;
int err;
size_t i, j;
uint32_t magic;
const uint8_t *p;
p = f;
i = n - 4;
err = kZipErrorEocdNotFound;
do {

View file

@ -16,10 +16,11 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/stdckdint.h"
#include "libc/str/str.h"
wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, size_t count) {
size_t bytes;
if (__builtin_mul_overflow(count, sizeof(wchar_t), &bytes)) bytes = -1;
if (ckd_mul(&bytes, count, sizeof(wchar_t))) bytes = -1;
return memcpy(dest, src, bytes);
}

View file

@ -16,10 +16,11 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/stdckdint.h"
#include "libc/str/str.h"
wchar_t *wmemmove(wchar_t *dest, const wchar_t *src, size_t count) {
size_t bytes;
if (__builtin_mul_overflow(count, sizeof(wchar_t), &bytes)) bytes = -1;
if (ckd_mul(&bytes, count, sizeof(wchar_t))) bytes = -1;
return memmove(dest, src, bytes);
}

View file

@ -16,10 +16,11 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/stdckdint.h"
#include "libc/str/str.h"
wchar_t *wmempcpy(wchar_t *dest, const wchar_t *src, size_t count) {
size_t bytes;
if (__builtin_mul_overflow(count, sizeof(wchar_t), &bytes)) bytes = -1;
if (ckd_mul(&bytes, count, sizeof(wchar_t))) bytes = -1;
return mempcpy(dest, src, bytes);
}

View file

@ -19,6 +19,7 @@
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/stdckdint.h"
#include "libc/str/str.h"
typedef wchar_t xmm_t __attribute__((__vector_size__(16), __aligned__(4)));
@ -70,15 +71,11 @@ void *wmemrchr(const wchar_t *s, wchar_t c, size_t n) {
#ifdef __x86_64__
size_t bytes;
const void *r;
if (!IsTiny() && X86_HAVE(SSE)) {
if (IsAsan()) {
if (__builtin_mul_overflow(n, sizeof(wchar_t), &bytes)) bytes = -1;
__asan_verify(s, bytes);
}
r = wmemrchr_sse(s, c, n);
} else {
r = wmemrchr_pure(s, c, n);
if (IsAsan()) {
if (ckd_mul(&bytes, n, sizeof(wchar_t))) bytes = -1;
__asan_verify(s, bytes);
}
r = wmemrchr_sse(s, c, n);
return (void *)r;
#else
return wmemrchr_pure(s, c, n);

View file

@ -21,7 +21,7 @@
#include "libc/sysv/consts/o.h"
#include "libc/testlib/testlib.h"
STATIC_YOINK("zip_uri_support");
STATIC_YOINK("zipos");
/**
* Extracts zip asset to filesystem.

View file

@ -17,7 +17,7 @@
#include "libc/time/tz.internal.h"
#include "libc/time/tzfile.internal.h"
STATIC_YOINK("zip_uri_support");
STATIC_YOINK("zipos");
STATIC_YOINK("usr/share/zoneinfo/");
STATIC_YOINK("usr/share/zoneinfo/Anchorage");
STATIC_YOINK("usr/share/zoneinfo/Beijing");

View file

@ -26,6 +26,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/intrin/newbie.h"
#include "libc/macros.internal.h"
#include "libc/stdckdint.h"
#include "libc/str/str.h"
#include "libc/vga/vga.internal.h"
@ -53,8 +54,8 @@ static COLOR MAPCOLOR(struct Tty *tty, TtyCanvasColor ic) {
return ic;
}
static void DIRTY(struct Tty *tty, size_t gy1, size_t gx1,
size_t gy2, size_t gx2) {
static void DIRTY(struct Tty *tty, size_t gy1, size_t gx1, size_t gy2,
size_t gx2) {
if (tty->updy1 > gy1) tty->updy1 = gy1;
if (tty->updx1 > gx1) tty->updx1 = gx1;
if (tty->updy2 < gy2) tty->updy2 = gy2;
@ -66,14 +67,12 @@ static void RESETDIRTY(struct Tty *tty) {
}
unrollloops void _TtyBgr565Update(struct Tty *tty) {
size_t gy1 = tty->updy1, gy2 = tty->updy2,
gx1 = tty->updx1, gx2 = tty->updx2,
size_t gy1 = tty->updy1, gy2 = tty->updy2, gx1 = tty->updx1, gx2 = tty->updx2,
xsfb = tty->xsfb, xs = tty->xs;
if (gy1 < gy2 && gx1 < gx2) {
size_t yleft = gy2 - gy1, xleft;
char *cplotter = tty->fb + gy1 * xsfb + gx1 * sizeof(TtyBgr565Color);
const char *creader = tty->canvas + gy1 * xs
+ gx1 * sizeof(TtyCanvasColor);
const char *creader = tty->canvas + gy1 * xs + gx1 * sizeof(TtyCanvasColor);
RESETDIRTY(tty);
while (yleft-- != 0) {
TtyBgr565Color *plotter = (TtyBgr565Color *)cplotter;
@ -94,14 +93,12 @@ unrollloops void _TtyBgr565Update(struct Tty *tty) {
}
unrollloops void _TtyBgr555Update(struct Tty *tty) {
size_t gy1 = tty->updy1, gy2 = tty->updy2,
gx1 = tty->updx1, gx2 = tty->updx2,
size_t gy1 = tty->updy1, gy2 = tty->updy2, gx1 = tty->updx1, gx2 = tty->updx2,
xsfb = tty->xsfb, xs = tty->xs;
if (gy1 < gy2 && gx1 < gx2) {
size_t yleft = gy2 - gy1, xleft;
char *cplotter = tty->fb + gy1 * xsfb + gx1 * sizeof(TtyBgr555Color);
const char *creader = tty->canvas + gy1 * xs
+ gx1 * sizeof(TtyCanvasColor);
const char *creader = tty->canvas + gy1 * xs + gx1 * sizeof(TtyCanvasColor);
RESETDIRTY(tty);
while (yleft-- != 0) {
TtyBgr555Color *plotter = (TtyBgr555Color *)cplotter;
@ -122,14 +119,12 @@ unrollloops void _TtyBgr555Update(struct Tty *tty) {
}
unrollloops void _TtyBgrxUpdate(struct Tty *tty) {
size_t gy1 = tty->updy1, gy2 = tty->updy2,
gx1 = tty->updx1, gx2 = tty->updx2,
size_t gy1 = tty->updy1, gy2 = tty->updy2, gx1 = tty->updx1, gx2 = tty->updx2,
xsfb = tty->xsfb, xs = tty->xs;
if (gy1 < gy2 && gx1 < gx2) {
size_t yleft = gy2 - gy1, xleft;
char *cplotter = tty->fb + gy1 * xsfb + gx1 * sizeof(TtyBgrxColor);
const char *creader = tty->canvas + gy1 * xs
+ gx1 * sizeof(TtyCanvasColor);
const char *creader = tty->canvas + gy1 * xs + gx1 * sizeof(TtyCanvasColor);
RESETDIRTY(tty);
while (yleft-- != 0) {
TtyBgrxColor *plotter = (TtyBgrxColor *)cplotter;
@ -147,14 +142,12 @@ unrollloops void _TtyBgrxUpdate(struct Tty *tty) {
}
unrollloops void _TtyRgbxUpdate(struct Tty *tty) {
size_t gy1 = tty->updy1, gy2 = tty->updy2,
gx1 = tty->updx1, gx2 = tty->updx2,
size_t gy1 = tty->updy1, gy2 = tty->updy2, gx1 = tty->updx1, gx2 = tty->updx2,
xsfb = tty->xsfb, xs = tty->xs;
if (gy1 < gy2 && gx1 < gx2) {
size_t yleft = gy2 - gy1, xleft;
char *cplotter = tty->fb + gy1 * xsfb + gx1 * sizeof(TtyRgbxColor);
const char *creader = tty->canvas + gy1 * xs
+ gx1 * sizeof(TtyCanvasColor);
const char *creader = tty->canvas + gy1 * xs + gx1 * sizeof(TtyCanvasColor);
RESETDIRTY(tty);
while (yleft-- != 0) {
TtyRgbxColor *plotter = (TtyRgbxColor *)cplotter;
@ -165,8 +158,10 @@ unrollloops void _TtyRgbxUpdate(struct Tty *tty) {
while (xleft-- != 0) {
ic.w = reader->w;
++reader;
oc = (TtyRgbxColor){.rgb.r = ic.bgr.r, .rgb.g = ic.bgr.g,
.rgb.b = ic.bgr.b, .rgb.x = 0xff};
oc = (TtyRgbxColor){.rgb.r = ic.bgr.r,
.rgb.g = ic.bgr.g,
.rgb.b = ic.bgr.b,
.rgb.x = 0xff};
plotter->w = oc.w;
++plotter;
}
@ -188,15 +183,15 @@ static COLOR MAPCOLOR(struct Tty *tty, TtyCanvasColor ic) {
if (tty->type == PC_VIDEO_BGRX8888)
return ic.w;
else {
TtyRgbxColor oc = (TtyRgbxColor){.rgb.r = ic.bgr.r, .rgb.g = ic.bgr.g,
.rgb.b = ic.bgr.b, .rgb.x = 0xff};
TtyRgbxColor oc = (TtyRgbxColor){
.rgb.r = ic.bgr.r, .rgb.g = ic.bgr.g, .rgb.b = ic.bgr.b, .rgb.x = 0xff};
return oc.w;
}
#endif
}
static void DIRTY(struct Tty *tty, size_t gy1, size_t gx1,
size_t gy2, size_t gx2) {
static void DIRTY(struct Tty *tty, size_t gy1, size_t gx1, size_t gy2,
size_t gx2) {
}
static void RESETDIRTY(struct Tty *tty) {
@ -207,9 +202,9 @@ void UPDATE(struct Tty *tty) {
#endif /* KLOGTTY */
static void DRAWBITMAP(struct Tty *tty, size_t gy, size_t gx,
COLOR fg, COLOR bg, const uint8_t *bitmap,
size_t bm_ht, size_t bm_wid) {
static void DRAWBITMAP(struct Tty *tty, size_t gy, size_t gx, COLOR fg,
COLOR bg, const uint8_t *bitmap, size_t bm_ht,
size_t bm_wid) {
size_t xs = tty->xs;
char *cplotter = tty->canvas + gy * xs + gx * sizeof(COLOR);
size_t yleft = bm_ht, xleft;
@ -218,39 +213,39 @@ static void DRAWBITMAP(struct Tty *tty, size_t gy, size_t gx,
xleft = bm_wid;
while (xleft >= 8) {
uint8_t bits = *bitmap++;
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
*plotter++ = ckd_add(&bits, bits, bits) ? fg : bg;
*plotter++ = ckd_add(&bits, bits, bits) ? fg : bg;
*plotter++ = ckd_add(&bits, bits, bits) ? fg : bg;
*plotter++ = ckd_add(&bits, bits, bits) ? fg : bg;
*plotter++ = ckd_add(&bits, bits, bits) ? fg : bg;
*plotter++ = ckd_add(&bits, bits, bits) ? fg : bg;
*plotter++ = ckd_add(&bits, bits, bits) ? fg : bg;
*plotter++ = ckd_add(&bits, bits, bits) ? fg : bg;
xleft -= 8;
}
if (xleft) {
uint8_t bits = *bitmap++;
switch (xleft) {
default:
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
*plotter++ = ckd_add(&bits, bits, bits) ? fg : bg;
/* fall through */
case 6:
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
*plotter++ = ckd_add(&bits, bits, bits) ? fg : bg;
/* fall through */
case 5:
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
*plotter++ = ckd_add(&bits, bits, bits) ? fg : bg;
/* fall through */
case 4:
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
*plotter++ = ckd_add(&bits, bits, bits) ? fg : bg;
/* fall through */
case 3:
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
*plotter++ = ckd_add(&bits, bits, bits) ? fg : bg;
/* fall through */
case 2:
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
*plotter++ = ckd_add(&bits, bits, bits) ? fg : bg;
/* fall through */
case 1:
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
*plotter++ = ckd_add(&bits, bits, bits) ? fg : bg;
}
}
cplotter += xs;
@ -259,23 +254,21 @@ static void DRAWBITMAP(struct Tty *tty, size_t gy, size_t gx,
}
static MAYUNROLLLOOPS void FILLRECT(struct Tty *tty, size_t gy, size_t gx,
size_t fill_ht, size_t fill_wid,
COLOR bg) {
size_t fill_ht, size_t fill_wid, COLOR bg) {
size_t xs = tty->xs;
char *cplotter = tty->canvas + gy * xs + gx * sizeof(COLOR);
size_t yleft = fill_ht, xleft;
while (yleft-- != 0) {
COLOR *plotter = (COLOR *)cplotter;
size_t i;
for (i = 0; i < fill_wid; ++i)
*plotter++ = bg;
for (i = 0; i < fill_wid; ++i) *plotter++ = bg;
cplotter += xs;
}
DIRTY(tty, gy, gx, gy + fill_ht, gx + fill_wid);
}
static void MOVERECT(struct Tty *tty, size_t dgy, size_t dgx,
size_t sgy, size_t sgx, size_t ht, size_t wid) {
static void MOVERECT(struct Tty *tty, size_t dgy, size_t dgx, size_t sgy,
size_t sgx, size_t ht, size_t wid) {
size_t xs = tty->xs, xm = wid * sizeof(COLOR);
char *canvas = tty->canvas;
DIRTY(tty, dgy, dgx, dgy + ht, dgx + wid);
@ -298,8 +291,7 @@ void DRAWCHAR(struct Tty *tty, size_t y, size_t x, wchar_t wc) {
const uint8_t *glyph;
const size_t glyph_ht = ARRAYLEN(_vga_font_default_direct[0]);
COLOR fg = MAPCOLOR(tty, tty->fg), bg = MAPCOLOR(tty, tty->bg);
if ((tty->pr & kTtyFlip) != 0)
fg = bg, bg = MAPCOLOR(tty, tty->fg);
if ((tty->pr & kTtyFlip) != 0) fg = bg, bg = MAPCOLOR(tty, tty->fg);
if (wc < L' ' || wc >= L' ' + ARRAYLEN(_vga_font_default_direct))
glyph = _vga_font_default_direct[0];
else
@ -323,8 +315,8 @@ void ERASELINECELLS(struct Tty *tty, size_t y, size_t x, size_t n) {
FILLRECT(tty, y * yc, x * xc, yc, n * xc, MAPCOLOR(tty, tty->bg));
}
void MOVELINECELLS(struct Tty *tty, size_t dsty, size_t dstx,
size_t srcy, size_t srcx, size_t n) {
void MOVELINECELLS(struct Tty *tty, size_t dsty, size_t dstx, size_t srcy,
size_t srcx, size_t n) {
size_t yc = tty->yc, xc = tty->xc;
MOVERECT(tty, dsty * yc, dstx * xc, srcy * yc, srcx * xc, yc, n * xc);
}

View file

@ -1,221 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_ZIP_H_
#define COSMOPOLITAN_LIBC_ZIP_H_
#include "libc/calls/struct/timespec.h"
#include "libc/intrin/bits.h"
#include "libc/macros.internal.h"
#include "libc/str/str.h"
/**
* @fileoverview PKZIP Data Structures.
*/
#define kZipOk 0
#define kZipErrorEocdNotFound -1
#define kZipErrorEocdOffsetOverflow -2
#define kZipErrorEocdMagicNotFound -3
#define kZipErrorEocdSizeOverflow -4
#define kZipErrorEocdDiskMismatch -5
#define kZipErrorCdirRecordsMismatch -6
#define kZipErrorCdirRecordsOverflow -7
#define kZipErrorCdirOffsetPastEocd -8
#define kZipErrorCdirLocatorMagic -9
#define kZipErrorCdirLocatorOffset -10
#define kZipErrorRaceCondition -11
#define kZipErrorMapFailed -12
#define kZipErrorOpenFailed -13
#define kZipAlign 2
#define kZipCosmopolitanVersion kZipEra2001
#define kZipOsDos 0
#define kZipOsAmiga 1
#define kZipOsOpenvms 2
#define kZipOsUnix 3
#define kZipOsVmcms 4
#define kZipOsAtarist 5
#define kZipOsOs2hpfs 6
#define kZipOsMacintosh 7
#define kZipOsZsystem 8
#define kZipOsCpm 9
#define kZipOsWindowsntfs 10
#define kZipOsMvsos390zos 11
#define kZipOsVse 12
#define kZipOsAcornrisc 13
#define kZipOsVfat 14
#define kZipOsAltmvs 15
#define kZipOsBeos 16
#define kZipOsTandem 17
#define kZipOsOs400 18
#define kZipOsOsxdarwin 19
#define kZipEra1989 10 /* PKZIP 1.0 */
#define kZipEra1993 20 /* PKZIP 2.0: deflate/subdir/etc. support */
#define kZipEra2001 45 /* PKZIP 4.5: kZipExtraZip64 support */
#define kZipIattrBinary 0 /* first bit not set */
#define kZipIattrText 1 /* first bit set */
#define kZipCompressionNone 0
#define kZipCompressionDeflate 8
#define kZipCdirHdrMagic 0x06054b50 /* PK♣♠ "PK\5\6" */
#define kZipCdirHdrMinSize 22
#define kZipCdirAlign kZipAlign
#define kZipCdirHdrLinkableSize 294
#define kZipCdir64HdrMagic 0x06064b50 /* PK♣♠ "PK\6\6" */
#define kZipCdir64HdrMinSize 56
#define kZipCdir64LocatorMagic 0x07064b50 /* PK♠• "PK\6\7" */
#define kZipCdir64LocatorSize 20
#define kZipCfileHdrMagic 0x02014b50 /* PK☺☻ "PK\1\2" */
#define kZipCfileHdrMinSize 46
#define kZipCfileOffsetGeneralflag 8
#define kZipCfileOffsetCompressionmethod 10
#define kZipCfileOffsetLastmodifiedtime 12
#define kZipCfileOffsetLastmodifieddate 14
#define kZipCfileOffsetCrc32 16
#define kZipCfileOffsetCompressedsize 20
#define kZipCfileOffsetUncompressedsize 24
#define kZipCfileOffsetExternalattributes 38
#define kZipCfileOffsetOffset 42
#define kZipLfileHdrMagic 0x04034b50 /* PK♥♦ "PK\3\4" */
#define kZipLfileHdrMinSize 30
#define kZipLfileOffsetGeneralflag 6
#define kZipLfileOffsetCompressionmethod 8
#define kZipLfileOffsetLastmodifiedtime 10
#define kZipLfileOffsetLastmodifieddate 12
#define kZipLfileOffsetCrc32 14
#define kZipLfileOffsetCompressedsize 18
#define kZipLfileOffsetUncompressedsize 22
#define kZipGflagUtf8 0x800
#define kZipExtraHdrSize 4
#define kZipExtraZip64 0x0001
#define kZipExtraNtfs 0x000a
#define kZipExtraUnix 0x000d
#define kZipExtraExtendedTimestamp 0x5455
#define kZipExtraInfoZipNewUnixExtra 0x7875
#define kZipCfileMagic "PK\001\002"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
/* end of central directory record */
#define ZIP_CDIR_MAGIC(P) READ32LE(P)
#define ZIP_CDIR_DISK(P) READ16LE((P) + 4)
#define ZIP_CDIR_STARTINGDISK(P) READ16LE((P) + 6)
#define ZIP_CDIR_RECORDSONDISK(P) READ16LE((P) + 8)
#define ZIP_CDIR_RECORDS(P) READ16LE((P) + 10)
#define ZIP_CDIR_SIZE(P) READ32LE((P) + 12)
#define ZIP_CDIR_OFFSET(P) READ32LE((P) + 16)
#define ZIP_CDIR_COMMENTSIZE(P) READ16LE((P) + 20)
#define ZIP_CDIR_COMMENT(P) ((P) + 22) /* recommend stopping at nul */
#define ZIP_CDIR_HDRSIZE(P) (ZIP_CDIR_COMMENTSIZE(P) + kZipCdirHdrMinSize)
/* zip64 end of central directory record */
#define ZIP_CDIR64_MAGIC(P) READ32LE(P)
#define ZIP_CDIR64_HDRSIZE(P) (READ64LE((P) + 4) + 12)
#define ZIP_CDIR64_VERSIONMADE(P) READ16LE((P) + 12)
#define ZIP_CDIR64_VERSIONNEED(P) READ16LE((P) + 14)
#define ZIP_CDIR64_DISK(P) READ32LE((P) + 16)
#define ZIP_CDIR64_STARTINGDISK(P) READ32LE((P) + 20)
#define ZIP_CDIR64_RECORDSONDISK(P) READ64LE((P) + 24)
#define ZIP_CDIR64_RECORDS(P) READ64LE((P) + 32)
#define ZIP_CDIR64_SIZE(P) READ64LE((P) + 40)
#define ZIP_CDIR64_OFFSET(P) READ64LE((P) + 48)
#define ZIP_CDIR64_COMMENTSIZE(P) \
(ZIP_CDIR64_HDRSIZE(P) >= 56 ? ZIP_CDIR64_HDRSIZE(P) - 56 : 0)
#define ZIP_CDIR64_COMMENT(P) ((P) + 56) /* recommend stopping at nul */
#define ZIP_LOCATE64_MAGIC(P) READ32LE(P)
#define ZIP_LOCATE64_STARTINGDISK(P) READ32LE((P) + 4)
#define ZIP_LOCATE64_OFFSET(P) READ64LE((P) + 8)
#define ZIP_LOCATE64_TOTALDISKS(P) READ32LE((P) + 12)
/* central directory file header */
#define ZIP_CFILE_MAGIC(P) READ32LE(P)
#define ZIP_CFILE_VERSIONMADE(P) (255 & (P)[4])
#define ZIP_CFILE_FILEATTRCOMPAT(P) (255 & (P)[5])
#define ZIP_CFILE_VERSIONNEED(P) (255 & (P)[6])
#define ZIP_CFILE_OSNEED(P) (255 & (P)[7])
#define ZIP_CFILE_GENERALFLAG(P) READ16LE((P) + kZipCfileOffsetGeneralflag)
#define ZIP_CFILE_COMPRESSIONMETHOD(P) \
READ16LE((P) + kZipCfileOffsetCompressionmethod)
#define ZIP_CFILE_LASTMODIFIEDTIME(P) \
READ16LE((P) + kZipCfileOffsetLastmodifiedtime) /* @see DOS_TIME() */
#define ZIP_CFILE_LASTMODIFIEDDATE(P) \
READ16LE((P) + kZipCfileOffsetLastmodifieddate) /* @see DOS_DATE() */
#define ZIP_CFILE_CRC32(P) READ32LE((P) + kZipCfileOffsetCrc32)
#define ZIP_CFILE_COMPRESSEDSIZE(P) READ32LE(P + kZipCfileOffsetCompressedsize)
#define ZIP_CFILE_UNCOMPRESSEDSIZE(P) \
READ32LE((P) + kZipCfileOffsetUncompressedsize)
#define ZIP_CFILE_NAMESIZE(P) READ16LE((P) + 28)
#define ZIP_CFILE_EXTRASIZE(P) READ16LE((P) + 30)
#define ZIP_CFILE_COMMENTSIZE(P) READ16LE((P) + 32)
#define ZIP_CFILE_DISK(P) READ16LE((P) + 34)
#define ZIP_CFILE_INTERNALATTRIBUTES(P) READ16LE((P) + 36)
#define ZIP_CFILE_EXTERNALATTRIBUTES(P) \
READ32LE((P) + kZipCfileOffsetExternalattributes)
#define ZIP_CFILE_OFFSET(P) READ32LE((P) + kZipCfileOffsetOffset)
#define ZIP_CFILE_NAME(P) ((const char *)((P) + 46)) /* not nul-terminated */
#define ZIP_CFILE_EXTRA(P) ((P) + 46 + ZIP_CFILE_NAMESIZE(P))
#define ZIP_CFILE_COMMENT(P) \
((const char *)((P) + 46 + ZIP_CFILE_NAMESIZE(P) + \
ZIP_CFILE_EXTRASIZE(P))) /* recommend stopping at nul */
#define ZIP_CFILE_HDRSIZE(P) \
(ZIP_CFILE_NAMESIZE(P) + ZIP_CFILE_EXTRASIZE(P) + ZIP_CFILE_COMMENTSIZE(P) + \
kZipCfileHdrMinSize)
/* local file header */
#define ZIP_LFILE_MAGIC(P) READ32LE(P)
#define ZIP_LFILE_VERSIONNEED(P) (255 & (P)[4])
#define ZIP_LFILE_OSNEED(P) (255 & (P)[5])
#define ZIP_LFILE_GENERALFLAG(P) READ16LE((P) + kZipLfileOffsetGeneralflag)
#define ZIP_LFILE_COMPRESSIONMETHOD(P) \
READ16LE((P) + kZipLfileOffsetCompressionmethod)
#define ZIP_LFILE_LASTMODIFIEDTIME(P) \
READ16LE((P) + kZipLfileOffsetLastmodifiedtime) /* @see DOS_TIME() */
#define ZIP_LFILE_LASTMODIFIEDDATE(P) \
READ16LE((P) + kZipLfileOffsetLastmodifieddate) /* @see DOS_DATE() */
#define ZIP_LFILE_CRC32(P) READ32LE((P) + kZipLfileOffsetCrc32)
#define ZIP_LFILE_COMPRESSEDSIZE(P) \
READ32LE((P) + kZipLfileOffsetCompressedsize)
#define ZIP_LFILE_UNCOMPRESSEDSIZE(P) \
READ32LE((P) + kZipLfileOffsetUncompressedsize)
#define ZIP_LFILE_NAMESIZE(P) READ16LE((P) + 26)
#define ZIP_LFILE_EXTRASIZE(P) READ16LE((P) + 28)
#define ZIP_LFILE_NAME(P) ((const char *)((P) + 30))
#define ZIP_LFILE_EXTRA(P) ((P) + 30 + ZIP_LFILE_NAMESIZE(P))
#define ZIP_LFILE_HDRSIZE(P) \
(ZIP_LFILE_NAMESIZE(P) + ZIP_LFILE_EXTRASIZE(P) + kZipLfileHdrMinSize)
#define ZIP_LFILE_CONTENT(P) ((P) + ZIP_LFILE_HDRSIZE(P))
#define ZIP_LFILE_SIZE(P) (ZIP_LFILE_HDRSIZE(P) + ZIP_LFILE_COMPRESSEDSIZE(P))
#define ZIP_EXTRA_HEADERID(P) READ16LE(P)
#define ZIP_EXTRA_CONTENTSIZE(P) READ16LE((P) + 2)
#define ZIP_EXTRA_CONTENT(P) ((P) + 4)
#define ZIP_EXTRA_SIZE(P) (ZIP_EXTRA_CONTENTSIZE(P) + kZipExtraHdrSize)
void *GetZipEocd(const uint8_t *, size_t, int *);
uint8_t *FindEmbeddedApe(const uint8_t *, size_t);
int IsZipEocd32(const uint8_t *, size_t, size_t);
int IsZipEocd64(const uint8_t *, size_t, size_t);
int GetZipCfileMode(const uint8_t *);
uint64_t GetZipCdirOffset(const uint8_t *);
uint64_t GetZipCdirRecords(const uint8_t *);
void *GetZipCdirComment(const uint8_t *);
uint64_t GetZipCdirSize(const uint8_t *);
uint64_t GetZipCdirCommentSize(const uint8_t *);
uint64_t GetZipCfileUncompressedSize(const uint8_t *);
uint64_t GetZipCfileCompressedSize(const uint8_t *);
uint64_t GetZipCfileOffset(const uint8_t *);
uint64_t GetZipLfileUncompressedSize(const uint8_t *);
uint64_t GetZipLfileCompressedSize(const uint8_t *);
void GetZipCfileTimestamps(const uint8_t *, struct timespec *,
struct timespec *, struct timespec *, int);
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_ZIP_H_ */

View file

@ -59,10 +59,18 @@
#define kZipCompressionNone 0
#define kZipCompressionDeflate 8
#define kZipCdirHdrMagic 0x06054b50 /* PK♣♠ "PK\5\6" */
#define kZipCdirHdrMinSize 22
#define kZipCdirAlign kZipAlign
#define kZipCdirHdrLinkableSize 294
#define kZipCdirHdrMagic 0x06054b50 /* PK♣♠ "PK\5\6" */
#define kZipCdirHdrMagicTodo 0x19184b50 /* PK♣♠ "PK\30\31" */
#define kZipCdirHdrMinSize 22
#define kZipCdirAlign kZipAlign
#define kZipCdirHdrLinkableSize 294
#define kZipCdirDiskOffset 4
#define kZipCdirStartingDiskOffset 6
#define kZipCdirRecordsOnDiskOffset 8
#define kZipCdirRecordsOffset 10
#define kZipCdirSizeOffset 12
#define kZipCdirOffsetOffset 16
#define kZipCdirCommentSizeOffset 20
#define kZipCdir64HdrMagic 0x06064b50 /* PK♣♠ "PK\6\6" */
#define kZipCdir64HdrMinSize 56
@ -106,13 +114,13 @@
/* end of central directory record */
#define ZIP_CDIR_MAGIC(P) READ32LE(P)
#define ZIP_CDIR_DISK(P) READ16LE((P) + 4)
#define ZIP_CDIR_STARTINGDISK(P) READ16LE((P) + 6)
#define ZIP_CDIR_RECORDSONDISK(P) READ16LE((P) + 8)
#define ZIP_CDIR_RECORDS(P) READ16LE((P) + 10)
#define ZIP_CDIR_SIZE(P) READ32LE((P) + 12)
#define ZIP_CDIR_OFFSET(P) READ32LE((P) + 16)
#define ZIP_CDIR_COMMENTSIZE(P) READ16LE((P) + 20)
#define ZIP_CDIR_DISK(P) READ16LE((P) + kZipCdirDiskOffset)
#define ZIP_CDIR_STARTINGDISK(P) READ16LE((P) + kZipCdirStartingDiskOffset)
#define ZIP_CDIR_RECORDSONDISK(P) READ16LE((P) + kZipCdirRecordsOnDiskOffset)
#define ZIP_CDIR_RECORDS(P) READ16LE((P) + kZipCdirRecordsOffset)
#define ZIP_CDIR_SIZE(P) READ32LE((P) + kZipCdirSizeOffset)
#define ZIP_CDIR_OFFSET(P) READ32LE((P) + kZipCdirOffsetOffset)
#define ZIP_CDIR_COMMENTSIZE(P) READ16LE((P) + kZipCdirCommentSizeOffset)
#define ZIP_CDIR_COMMENT(P) ((P) + 22) /* recommend stopping at nul */
#define ZIP_CDIR_HDRSIZE(P) (ZIP_CDIR_COMMENTSIZE(P) + kZipCdirHdrMinSize)
@ -199,7 +207,7 @@
#define ZIP_EXTRA_CONTENT(P) ((P) + 4)
#define ZIP_EXTRA_SIZE(P) (ZIP_EXTRA_CONTENTSIZE(P) + kZipExtraHdrSize)
void *GetZipEocd(const uint8_t *, size_t, int *);
void *GetZipEocd(const void *, size_t, int *);
uint8_t *FindEmbeddedApe(const uint8_t *, size_t);
int IsZipEocd32(const uint8_t *, size_t, size_t);
int IsZipEocd64(const uint8_t *, size_t, size_t);

View file

@ -22,8 +22,6 @@
zipos = 0
.globl zipos
.yoink __zip_end
.yoink __zip_start
.yoink __zipos_close
.yoink __zipos_fcntl
.yoink __zipos_fstat

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.internal.h"
#include "libc/stdckdint.h"
#include "libc/str/str.h"
#include "net/http/http.h"
@ -44,16 +45,16 @@ bool ParseHttpRange(const char *p, size_t n, long resourcelength,
++p, --n;
length = 0;
while (n && '0' <= *p && *p <= '9') {
if (__builtin_mul_overflow(length, 10, &length)) return false;
if (__builtin_add_overflow(length, *p - '0', &length)) return false;
if (ckd_mul(&length, length, 10)) return false;
if (ckd_add(&length, length, *p - '0')) return false;
++p, --n;
}
if (__builtin_sub_overflow(resourcelength, length, &start)) return false;
if (ckd_sub(&start, resourcelength, length)) return false;
} else {
start = 0;
while (n && '0' <= *p && *p <= '9') {
if (__builtin_mul_overflow(start, 10, &start)) return false;
if (__builtin_add_overflow(start, *p - '0', &start)) return false;
if (ckd_mul(&start, start, 10)) return false;
if (ckd_add(&start, start, *p - '0')) return false;
++p, --n;
}
if (n && *p == '-') {
@ -63,14 +64,14 @@ bool ParseHttpRange(const char *p, size_t n, long resourcelength,
} else {
length = 0;
while (n && '0' <= *p && *p <= '9') {
if (__builtin_mul_overflow(length, 10, &length)) return false;
if (__builtin_add_overflow(length, *p - '0', &length)) return false;
if (ckd_mul(&length, length, 10)) return false;
if (ckd_add(&length, length, *p - '0')) return false;
++p, --n;
}
if (__builtin_add_overflow(length, 1, &length)) return false;
if (__builtin_sub_overflow(length, start, &length)) return false;
if (ckd_add(&length, length, 1)) return false;
if (ckd_sub(&length, length, start)) return false;
}
} else if (__builtin_sub_overflow(resourcelength, start, &length)) {
} else if (ckd_sub(&length, resourcelength, start)) {
return false;
}
}
@ -78,7 +79,7 @@ bool ParseHttpRange(const char *p, size_t n, long resourcelength,
if (start < 0) return false;
if (length < 1) return false;
if (start > resourcelength) return false;
if (__builtin_add_overflow(start, length, &ending)) return false;
if (ckd_add(&ending, start, length)) return false;
if (ending > resourcelength) {
length = resourcelength - start;
}

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/stdckdint.h"
#include "libc/str/str.h"
#include "net/http/ip.h"
@ -36,8 +37,8 @@ int64_t ParseIp(const char *s, size_t n) {
for (b = x = j = i = 0; i < n; ++i) {
c = s[i] & 255;
if (isdigit(c)) {
if (__builtin_mul_overflow(b, 10, &b) || //
__builtin_add_overflow(b, c - '0', &b) || //
if (ckd_mul(&b, b, 10) || //
ckd_add(&b, b, c - '0') || //
(b > 255 && dotted)) {
return -1;
}

View file

@ -18,7 +18,7 @@
*/
#include "net/https/https.h"
STATIC_YOINK("zip_uri_support");
STATIC_YOINK("zipos");
STATIC_YOINK("usr/share/ssl/root/");
STATIC_YOINK("usr/share/ssl/root/amazon.pem");
STATIC_YOINK("usr/share/ssl/root/certum.pem");

View file

@ -30,7 +30,7 @@
#ifdef __x86_64__
STATIC_YOINK("zip_uri_support");
STATIC_YOINK("zipos");
int fds[2];
char buf[8];

View file

@ -44,7 +44,7 @@
#include "libc/time/struct/tm.h"
#include "libc/time/time.h"
STATIC_YOINK("zip_uri_support");
STATIC_YOINK("zipos");
STATIC_YOINK("libc/testlib/hyperion.txt");
#define THREADS 8

View file

@ -34,7 +34,7 @@
#include "libc/testlib/testlib.h"
#include "libc/x/x.h"
STATIC_YOINK("zip_uri_support");
STATIC_YOINK("zipos");
char testlib_enable_tmp_setup_teardown;

View file

@ -20,7 +20,7 @@
#include "libc/str/str.h"
#include "libc/sysv/consts/o.h"
STATIC_YOINK("zip_uri_support");
STATIC_YOINK("zipos");
int main(int argc, char *argv[]) {
int fd = open("/zip/life.elf", O_RDONLY);

View file

@ -49,7 +49,7 @@
#include "libc/x/xspawn.h"
#include "third_party/xed/x86.h"
STATIC_YOINK("zip_uri_support");
STATIC_YOINK("zipos");
char testlib_enable_tmp_setup_teardown;

View file

@ -87,7 +87,7 @@ o/$(MODE)/test/libc/runtime/prog/ftraceasm.elf: \
$(TEST_LIBC_RUNTIME_DEPS) \
o/$(MODE)/test/libc/runtime/prog/ftraceasm.o \
o/$(MODE)/test/libc/runtime/runtime.pkg
@$(ELFLINK) --gc-sections
@$(ELFLINK)
o/$(MODE)/test/libc/runtime/prog/ftraceasm.txt: \
o/$(MODE)/test/libc/runtime/prog/ftraceasm.elf
@$(OBJDUMP) -d $< >$@

View file

@ -29,7 +29,7 @@
#include "libc/x/xasprintf.h"
#include "libc/x/xiso8601.h"
STATIC_YOINK("zip_uri_support");
STATIC_YOINK("zipos");
STATIC_YOINK("usr/share/zoneinfo/New_York");
char testlib_enable_tmp_setup_teardown;
@ -61,20 +61,20 @@ TEST(opendir, enotdir) {
TEST(opendir, zipTest_fake) {
ASSERT_NE(NULL, (dir = opendir("/zip")));
EXPECT_NE(NULL, (ent = readdir(dir)));
EXPECT_STREQ(".cosmo", ent->d_name);
EXPECT_NE(NULL, (ent = readdir(dir)));
EXPECT_STREQ("echo", ent->d_name);
EXPECT_NE(NULL, (ent = readdir(dir)));
EXPECT_STREQ("usr", ent->d_name);
EXPECT_NE(NULL, (ent = readdir(dir)));
EXPECT_STREQ(".cosmo", ent->d_name);
EXPECT_EQ(NULL, (ent = readdir(dir)));
EXPECT_EQ(0, closedir(dir));
ASSERT_NE(NULL, (dir = opendir("/zip/")));
EXPECT_NE(NULL, (ent = readdir(dir)));
EXPECT_STREQ(".cosmo", ent->d_name);
EXPECT_NE(NULL, (ent = readdir(dir)));
EXPECT_STREQ("echo", ent->d_name);
EXPECT_NE(NULL, (ent = readdir(dir)));
EXPECT_STREQ("usr", ent->d_name);
EXPECT_NE(NULL, (ent = readdir(dir)));
EXPECT_STREQ(".cosmo", ent->d_name);
EXPECT_EQ(NULL, (ent = readdir(dir)));
EXPECT_EQ(0, closedir(dir));
ASSERT_NE(NULL, (dir = opendir("/zip/usr")));

View file

@ -26,7 +26,7 @@
#include "libc/testlib/testlib.h"
#include "libc/thread/spawn.h"
STATIC_YOINK("zip_uri_support");
STATIC_YOINK("zipos");
STATIC_YOINK("libc/testlib/hyperion.txt");
STATIC_YOINK("inflate");
STATIC_YOINK("inflateInit2");

View file

@ -41,7 +41,7 @@
#include "third_party/regex/regex.h"
#ifdef __x86_64__
STATIC_YOINK("zip_uri_support");
STATIC_YOINK("zipos");
STATIC_YOINK("o/" MODE "/test/tool/net/redbean-tester.com");
char testlib_enable_tmp_setup_teardown_once;

View file

@ -17,11 +17,11 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/mem/copyfd.internal.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
#include "libc/macros.internal.h"
#include "libc/mem/copyfd.internal.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
@ -30,7 +30,7 @@
#include "libc/sysv/consts/sig.h"
#include "libc/testlib/testlib.h"
STATIC_YOINK("zip_uri_support");
STATIC_YOINK("zipos");
STATIC_YOINK("plinko.com");
STATIC_YOINK("library.lisp");
STATIC_YOINK("library_test.lisp");

View file

@ -1,4 +1,5 @@
#include "libc/math.h"
#include "libc/stdckdint.h"
#include "third_party/chibicc/test/test.h"
#define FPNAN 0
@ -194,28 +195,28 @@ void test_memcpy(void) {
void test_add_overflow(void) {
{
int z;
ASSERT(0, __builtin_add_overflow(2, 3, &z));
ASSERT(0, ckd_add(&z, 2, 3));
ASSERT(5, z);
}
{
int x, y, z;
x = 2;
y = 3;
ASSERT(0, __builtin_add_overflow(x, y, &z));
ASSERT(0, ckd_add(&z, x, y));
ASSERT(5, z);
}
{
int x, y, z;
x = 0x7fffffff;
y = 1;
ASSERT(1, __builtin_add_overflow(x, y, &z));
ASSERT(1, ckd_add(&z, x, y));
ASSERT(-2147483648, z);
}
{
long x, y, z;
x = 0x7fffffff;
y = 1;
ASSERT(0, __builtin_add_overflow(x, y, &z));
ASSERT(0, ckd_add(&z, x, y));
ASSERT(2147483648, z);
}
}
@ -225,21 +226,21 @@ void test_sub_overflow(void) {
int x, y, z;
x = 2;
y = 3;
ASSERT(0, __builtin_sub_overflow(x, y, &z));
ASSERT(0, ckd_sub(&z, x, y));
ASSERT(-1, z);
}
{
int x, y, z;
x = -2147483648;
y = 1;
ASSERT(1, __builtin_sub_overflow(x, y, &z));
ASSERT(1, ckd_sub(&z, x, y));
ASSERT(2147483647, z);
}
{
long x, y, z;
x = -2147483648;
y = 1;
ASSERT(0, __builtin_sub_overflow(x, y, &z));
ASSERT(0, ckd_sub(&z, x, y));
ASSERT(-2147483649, z);
}
}
@ -249,21 +250,21 @@ void test_mul_overflow(void) {
int x, y, z;
x = 2;
y = 3;
ASSERT(0, __builtin_mul_overflow(x, y, &z));
ASSERT(0, ckd_mul(&z, x, y));
ASSERT(6, z);
}
{
int x, y, z;
x = 2147483647;
y = 2;
ASSERT(1, __builtin_mul_overflow(x, y, &z));
ASSERT(1, ckd_mul(&z, x, y));
ASSERT(-2, z);
}
{
long x, y, z;
x = 2147483647;
y = 2;
ASSERT(0, __builtin_mul_overflow(x, y, &z));
ASSERT(0, ckd_mul(&z, x, y));
ASSERT(4294967294, z);
}
}

View file

@ -11,6 +11,7 @@
#include "libc/nexgen32e/rdtsc.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/sysconf.h"
#include "libc/stdckdint.h"
#include "libc/stdio/rand.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
@ -829,7 +830,7 @@ void dlfree(void* mem) {
void* dlcalloc(size_t n_elements, size_t elem_size) {
void* mem;
size_t req = 0;
if (__builtin_mul_overflow(n_elements, elem_size, &req)) req = -1;
if (ckd_mul(&req, n_elements, elem_size)) req = -1;
mem = dlmalloc(req);
if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
bzero(mem, req);

View file

@ -155,6 +155,7 @@
#include "libc/runtime/runtime.h"
#include "libc/sock/sock.h"
#include "libc/sock/struct/pollfd.h"
#include "libc/stdckdint.h"
#include "libc/stdio/append.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
@ -2011,8 +2012,7 @@ ssize_t linenoiseEdit(struct linenoiseState *l, const char *prompt, char **obuf,
itemlen = linenoiseMaxCompletionWidth(&l->lc) + 4;
xn = MAX(1, (l->ws.ws_col - 1) / itemlen);
yn = (l->lc.len + (xn - 1)) / xn;
if (!__builtin_mul_overflow(xn, yn, &xy) &&
(p = calloc(xy, sizeof(char *)))) {
if (!ckd_mul(&xy, xn, yn) && (p = calloc(xy, sizeof(char *)))) {
// arrange in column major order
for (i = x = 0; x < xn; ++x) {
for (y = 0; y < yn; ++y) {

View file

@ -50,7 +50,7 @@ Copyright ARM Limited\\n\
Copyright Mbed TLS Contributors\"");
asm(".include \"libc/disclaimer.inc\"");
STATIC_YOINK("zip_uri_support");
STATIC_YOINK("zipos");
#if defined(MBEDTLS_PLATFORM_C)
static mbedtls_platform_context platform_ctx;

View file

@ -13,4 +13,4 @@ Copyright ARM Limited\\n\
Copyright Mbed TLS Contributors\"");
asm(".include \"libc/disclaimer.inc\"");
STATIC_YOINK("zip_uri_support");
STATIC_YOINK("zipos");

View file

@ -41,7 +41,7 @@
#define USE_COSMO_CRASH MODE_DBG + 0
STATIC_YOINK("zip_uri_support");
STATIC_YOINK("zipos");
PYTHON_YOINK("_bootlocale");
PYTHON_YOINK("_locale");
PYTHON_YOINK("encodings.aliases");

View file

@ -234,7 +234,6 @@ static bool nocompress;
static bool isunittest;
static bool insertrunner;
static bool insertlauncher;
static uint64_t image_base;
static int strip_components;
static struct ElfWriter *elf;
static const char *path_prefix;
@ -246,7 +245,6 @@ static void
GetOpts(int argc, char *argv[])
{
int opt;
image_base = IMAGE_BASE_VIRTUAL;
path_prefix = ".python";
while ((opt = getopt(argc, argv, "hnmtr0Bb:O:o:C:P:Y:")) != -1) {
switch (opt) {
@ -279,9 +277,6 @@ GetOpts(int argc, char *argv[])
case 'C':
strip_components = atoi(optarg);
break;
case 'b':
image_base = strtoul(optarg, NULL, 0);
break;
case 'Y':
yoinks.p = realloc(yoinks.p, ++yoinks.n * sizeof(*yoinks.p));
yoinks.p[yoinks.n - 1] = xstrdup(optarg);
@ -656,22 +651,18 @@ Objectify(void)
if (ispkg) {
elfwriter_zip(elf, zipdir, zipdir, strlen(zipdir),
pydata, 0, 040755, timestamp, timestamp,
timestamp, nocompress, image_base,
kZipCdirHdrLinkableSize);
timestamp, nocompress);
}
if (!binonly) {
elfwriter_zip(elf, gc(xstrcat("py:", modname)), zipfile,
strlen(zipfile), pydata, pysize, st.st_mode, timestamp,
timestamp, timestamp, nocompress, image_base,
kZipCdirHdrLinkableSize);
timestamp, timestamp, nocompress);
}
elfwriter_zip(elf, gc(xstrcat("pyc:", modname)), gc(xstrcat(zipfile, 'c')),
strlen(zipfile) + 1, pycdata, pycsize, st.st_mode, timestamp,
timestamp, timestamp, nocompress, image_base,
kZipCdirHdrLinkableSize);
timestamp, timestamp, nocompress);
elfwriter_align(elf, 1, 0);
elfwriter_startsection(elf, ".yoink", SHT_PROGBITS,
SHF_ALLOC | SHF_EXECINSTR);
elfwriter_startsection(elf, ".yoink", SHT_PROGBITS, 0);
if (!(rc = AnalyzeModule(modname))) {
if (*path_prefix && !IsDot()) {
elfwriter_yoink(elf, gc(xstrcat(path_prefix, "/")), STB_GLOBAL);

Some files were not shown because too many files have changed in this diff Show more