diff --git a/libc/calls/calls.h b/libc/calls/calls.h index b5fd6d824..cd90cce73 100644 --- a/libc/calls/calls.h +++ b/libc/calls/calls.h @@ -69,48 +69,49 @@ COSMOPOLITAN_C_START_ /*───────────────────────────────────────────────────────────────────────────│─╗ │ cosmopolitan § system calls ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ +/* clang-format off */ typedef int sig_atomic_t; bool32 isatty(int) libcesque; -char *getcwd(char *, size_t) dontthrow; -char *realpath(const char *, char *) libcesque __wur; +char *getcwd(char *, size_t) dontthrow __write_only(1, 2); +char *realpath(const char *, char *) libcesque __wur __read_only(1) __write_only(2); char *ttyname(int) libcesque; -int access(const char *, int) libcesque; -int chdir(const char *) libcesque; -int chmod(const char *, unsigned) libcesque; -int chown(const char *, unsigned, unsigned) libcesque; -int chroot(const char *) libcesque; +int access(const char *, int) libcesque __read_only(1); +int chdir(const char *) libcesque __read_only(1); +int chmod(const char *, unsigned) libcesque __read_only(1); +int chown(const char *, unsigned, unsigned) libcesque __read_only(1); +int chroot(const char *) libcesque __read_only(1); int close(int) libcesque; int close_range(unsigned, unsigned, unsigned) libcesque; int closefrom(int) libcesque; -int creat(const char *, unsigned) libcesque; +int creat(const char *, unsigned) libcesque __read_only(1); int dup(int) libcesque; int dup2(int, int) libcesque; int dup3(int, int, int) libcesque; -int execl(const char *, const char *, ...) nullterminated() libcesque; -int execle(const char *, const char *, ...) nullterminated((1)) libcesque; -int execlp(const char *, const char *, ...) nullterminated() libcesque; -int execv(const char *, char *const[]) libcesque; -int execve(const char *, char *const[], char *const[]) libcesque; -int execvp(const char *, char *const[]) libcesque; -int faccessat(int, const char *, int, int) libcesque; +int execl(const char *, const char *, ...) nullterminated() libcesque __read_only(1) __read_only(2); +int execle(const char *, const char *, ...) nullterminated((1)) libcesque __read_only(1) __read_only(2); +int execlp(const char *, const char *, ...) nullterminated() libcesque __read_only(1) __read_only(2); +int execv(const char *, char *const[]) libcesque __read_only(1) __read_only(2); +int execve(const char *, char *const[], char *const[]) libcesque __read_only(1) __read_only(2) __read_only(3); +int execvp(const char *, char *const[]) libcesque __read_only(1) __read_only(2); +int faccessat(int, const char *, int, int) libcesque __read_only(2); int fchdir(int) libcesque; int fchmod(int, unsigned) libcesque; -int fchmodat(int, const char *, unsigned, int) libcesque; +int fchmodat(int, const char *, unsigned, int) libcesque __read_only(2); int fchown(int, unsigned, unsigned) libcesque; -int fchownat(int, const char *, unsigned, unsigned, int) libcesque; +int fchownat(int, const char *, unsigned, unsigned, int) libcesque __read_only(2); int fcntl(int, int, ...) libcesque; int fdatasync(int) libcesque; -int fexecve(int, char *const[], char *const[]) libcesque; +int fexecve(int, char *const[], char *const[]) libcesque __read_only(2) __read_only(3); int flock(int, int) libcesque; int fork(void) libcesque; int fsync(int) libcesque; int ftruncate(int, int64_t) libcesque; -int getdomainname(char *, size_t) libcesque; -int getgroups(int, unsigned[]) libcesque; -int gethostname(char *, size_t) libcesque; -int getloadavg(double *, int) libcesque; +int getdomainname(char *, size_t) libcesque __write_only(1, 2); +int getgroups(int, unsigned[]) libcesque __write_only(2, 1); +int gethostname(char *, size_t) libcesque __write_only(1, 2); +int getloadavg(double *, int) libcesque __write_only(1, 2); int getpgid(int) libcesque; int getpgrp(void) libcesque nosideeffect; int getpid(void) libcesque nosideeffect; @@ -121,35 +122,35 @@ int ioctl(int, unsigned long, ...) libcesque; int issetugid(void) libcesque; int kill(int, int) libcesque; int killpg(int, int) libcesque; -int lchmod(const char *, unsigned) libcesque; -int lchown(const char *, unsigned, unsigned) libcesque; -int link(const char *, const char *) libcesque; -int linkat(int, const char *, int, const char *, int) libcesque; -int mincore(void *, size_t, unsigned char *) libcesque; -int mkdir(const char *, unsigned) libcesque; -int mkdirat(int, const char *, unsigned) libcesque; -int mknod(const char *, unsigned, uint64_t) libcesque; +int lchmod(const char *, unsigned) libcesque __read_only(1); +int lchown(const char *, unsigned, unsigned) libcesque __read_only(1); +int link(const char *, const char *) libcesque __read_only(1) __read_only(2); +int linkat(int, const char *, int, const char *, int) libcesque __read_only(2) __read_only(4); +int mincore(void *, size_t, unsigned char *) libcesque __read_only(1) __write_only(3); +int mkdir(const char *, unsigned) libcesque __read_only(1); +int mkdirat(int, const char *, unsigned) libcesque __read_only(2); +int mknod(const char *, unsigned, uint64_t) libcesque __read_only(1); int nice(int) libcesque; -int open(const char *, int, ...) libcesque; -int openat(int, const char *, int, ...) libcesque; +int open(const char *, int, ...) libcesque __read_only(1); +int openat(int, const char *, int, ...) libcesque __read_only(2); int pause(void) libcesque; -int pipe(int[2]) libcesque; -int pipe2(int[2], int) libcesque; +int pipe(int[2]) libcesque __write_only(1); +int pipe2(int[2], int) libcesque __write_only(1); int posix_fadvise(int, int64_t, int64_t, int) libcesque; -int posix_madvise(void *, uint64_t, int) libcesque; +int posix_madvise(void *, uint64_t, int) libcesque __read_write(1); int raise(int) libcesque; int reboot(int) libcesque; -int remove(const char *) libcesque; -int rename(const char *, const char *) libcesque; -int renameat(int, const char *, int, const char *) libcesque; -int rmdir(const char *) libcesque; +int remove(const char *) libcesque __read_only(1); +int rename(const char *, const char *) libcesque __read_only(1) __read_only(2); +int renameat(int, const char *, int, const char *) libcesque __read_only(2) __read_only(4); +int rmdir(const char *) libcesque __read_only(1); int sched_yield(void) libcesque; int setegid(unsigned) libcesque; int seteuid(unsigned) libcesque; int setfsgid(unsigned) libcesque; int setfsuid(unsigned) libcesque; int setgid(unsigned) libcesque; -int setgroups(size_t, const unsigned[]) libcesque; +int setgroups(size_t, const unsigned[]) libcesque __read_only(2); int setpgid(int, int) libcesque; int setpgrp(void) libcesque; int setpriority(int, unsigned, int) libcesque; @@ -157,32 +158,32 @@ int setregid(unsigned, unsigned) libcesque; int setreuid(unsigned, unsigned) libcesque; int setsid(void) libcesque; int setuid(unsigned) libcesque; -int shm_open(const char *, int, unsigned) libcesque; -int shm_unlink(const char *) libcesque; +int shm_open(const char *, int, unsigned) libcesque __read_only(1); +int shm_unlink(const char *) libcesque __read_only(1); int sigignore(int) libcesque; int siginterrupt(int, int) libcesque; -int symlink(const char *, const char *) libcesque; -int symlinkat(const char *, int, const char *) libcesque; +int symlink(const char *, const char *) libcesque __read_only(1) __read_only(2); +int symlinkat(const char *, int, const char *) libcesque __read_only(1) __read_only(3); int tcgetpgrp(int) libcesque; int tcsetpgrp(int, int) libcesque; -int truncate(const char *, int64_t) libcesque; -int ttyname_r(int, char *, size_t) libcesque; -int unlink(const char *) libcesque; -int unlinkat(int, const char *, int) libcesque; +int truncate(const char *, int64_t) libcesque __read_only(1); +int ttyname_r(int, char *, size_t) libcesque __write_only(2, 3); +int unlink(const char *) libcesque __read_only(1); +int unlinkat(int, const char *, int) libcesque __read_only(2); int usleep(uint64_t) libcesque; int vfork(void) libcesque returnstwice; -int wait(int *) libcesque; -int waitpid(int, int *, int) libcesque; +int wait(int *) libcesque __write_only(1); +int waitpid(int, int *, int) libcesque __write_only(2); int64_t clock(void) libcesque; -int64_t time(int64_t *) libcesque; -ssize_t copy_file_range(int, long *, int, long *, size_t, unsigned) libcesque; +int64_t time(int64_t *) libcesque __write_only(1); +ssize_t copy_file_range(int, long *, int, long *, size_t, unsigned) libcesque __read_write(2) __read_write(4); ssize_t lseek(int, int64_t, int) libcesque; -ssize_t pread(int, void *, size_t, int64_t) libcesque; -ssize_t pwrite(int, const void *, size_t, int64_t) libcesque; -ssize_t read(int, void *, size_t) libcesque; -ssize_t readlink(const char *, char *, size_t) libcesque; -ssize_t readlinkat(int, const char *, char *, size_t) libcesque; -ssize_t write(int, const void *, size_t) libcesque; +ssize_t pread(int, void *, size_t, int64_t) libcesque __write_only(2, 3); +ssize_t pwrite(int, const void *, size_t, int64_t) libcesque __read_only(2); +ssize_t read(int, void *, size_t) libcesque __write_only(2, 3); +ssize_t readlink(const char *, char *, size_t) libcesque __read_only(1) __write_only(2, 3); +ssize_t readlinkat(int, const char *, char *, size_t) libcesque __read_only(2) __write_only(3, 4); +ssize_t write(int, const void *, size_t) libcesque __read_only(2); unsigned alarm(unsigned) libcesque; unsigned getegid(void) libcesque nosideeffect; unsigned geteuid(void) libcesque nosideeffect; @@ -199,50 +200,50 @@ int prctl(int, ...) libcesque; int gettid(void) libcesque; int setresgid(unsigned, unsigned, unsigned) libcesque; int setresuid(unsigned, unsigned, unsigned) libcesque; -int getresgid(unsigned *, unsigned *, unsigned *) libcesque; -int getresuid(unsigned *, unsigned *, unsigned *) libcesque; +int getresgid(unsigned *, unsigned *, unsigned *) libcesque __write_only(1) __write_only(2) __write_only(3); +int getresuid(unsigned *, unsigned *, unsigned *) libcesque __write_only(1) __write_only(2) __write_only(3); char *get_current_dir_name(void) libcesque __wur; -ssize_t splice(int, int64_t *, int, int64_t *, size_t, unsigned) libcesque; -int memfd_create(const char *, unsigned int) libcesque; -int execvpe(const char *, char *const[], char *const[]) libcesque; -int euidaccess(const char *, int) libcesque; -int eaccess(const char *, int) libcesque; -int madvise(void *, uint64_t, int) libcesque; -int getcpu(unsigned *, unsigned *) libcesque; +ssize_t splice(int, int64_t *, int, int64_t *, size_t, unsigned) libcesque __read_write(2) __read_write(4); +int memfd_create(const char *, unsigned int) libcesque __read_only(1); +int execvpe(const char *, char *const[], char *const[]) libcesque __read_only(1) __read_only(2) __read_only(3); +int euidaccess(const char *, int) libcesque __read_only(1); +int eaccess(const char *, int) libcesque __read_only(1); +int madvise(void *, uint64_t, int) libcesque __read_write(1); +int getcpu(unsigned *, unsigned *) libcesque __write_only(1) __write_only(2); #endif #ifdef _COSMO_SOURCE bool32 fdexists(int) libcesque; -bool32 fileexists(const char *) libcesque; +bool32 fileexists(const char *) libcesque __read_only(1); bool32 ischardev(int) libcesque; -bool32 isdirectory(const char *) libcesque; -bool32 isexecutable(const char *) libcesque; -bool32 isregularfile(const char *) libcesque; -bool32 issymlink(const char *) libcesque; -char *commandv(const char *, char *, size_t) libcesque; -int __getcwd(char *, size_t) libcesque; +bool32 isdirectory(const char *) libcesque __read_only(1); +bool32 isexecutable(const char *) libcesque __read_only(1); +bool32 isregularfile(const char *) libcesque __read_only(1); +bool32 issymlink(const char *) libcesque __read_only(1); +char *commandv(const char *, char *, size_t) libcesque __read_only(1) __write_only(2, 3); +int __getcwd(char *, size_t) libcesque __write_only(1, 2); int clone(void *, void *, size_t, int, void *, void *, void *, void *); int fadvise(int, uint64_t, uint64_t, int) libcesque; -int makedirs(const char *, unsigned) libcesque; -int pivot_root(const char *, const char *) libcesque; -int pledge(const char *, const char *) libcesque; -int seccomp(unsigned, unsigned, void *) libcesque; +int makedirs(const char *, unsigned) libcesque __read_only(1); +int pivot_root(const char *, const char *) libcesque __read_only(1) __read_only(2); +int pledge(const char *, const char *) libcesque __read_only(1) __read_only(2); +int seccomp(unsigned, unsigned, void *) libcesque __read_only(3); int sys_iopl(int) libcesque; int sys_ioprio_get(int, int) libcesque; int sys_ioprio_set(int, int, int) libcesque; -int sys_mlock(const void *, size_t) libcesque; -int sys_mlock2(const void *, size_t, int) libcesque; +int sys_mlock(const void *, size_t) libcesque __read_only(1); +int sys_mlock2(const void *, size_t, int) libcesque __read_only(1); int sys_mlockall(int) libcesque; -int sys_munlock(const void *, size_t) libcesque; +int sys_munlock(const void *, size_t) libcesque __read_only(1); int sys_munlockall(void) libcesque; int sys_personality(uint64_t) libcesque; int sys_ptrace(int, ...) libcesque; -int sysctl(int *, unsigned, void *, size_t *, void *, size_t) libcesque; -int sysctlbyname(const char *, void *, size_t *, void *, size_t) libcesque; -int sysctlnametomib(const char *, int *, size_t *) libcesque; +int sysctl(int *, unsigned, void *, size_t *, void *, size_t) libcesque __read_write(1) __read_write(4) __read_write(5); +int sysctlbyname(const char *, void *, size_t *, void *, size_t) libcesque __read_only(1) __write_only(2) __read_write(3) __read_only(4); +int sysctlnametomib(const char *, int *, size_t *) libcesque __read_only(1) __write_only(2) __read_write(3); int tmpfd(void) libcesque; -int touch(const char *, unsigned) libcesque; -int unveil(const char *, const char *) libcesque; +int touch(const char *, unsigned) libcesque __read_only(1); +int unveil(const char *, const char *) libcesque __read_only(1); long ptrace(int, ...) libcesque; ssize_t copyfd(int, int, size_t) libcesque; ssize_t readansi(int, char *, size_t) libcesque; diff --git a/libc/calls/ioctl.c b/libc/calls/ioctl.c index bd0c0642d..7eaa44a00 100644 --- a/libc/calls/ioctl.c +++ b/libc/calls/ioctl.c @@ -18,13 +18,13 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/assert.h" #include "libc/calls/internal.h" -#include "libc/intrin/fds.h" #include "libc/calls/syscall-sysv.internal.h" #include "libc/calls/syscall_support-nt.internal.h" #include "libc/calls/termios.h" #include "libc/dce.h" #include "libc/errno.h" #include "libc/intrin/cmpxchg.h" +#include "libc/intrin/fds.h" #include "libc/intrin/strace.h" #include "libc/intrin/weaken.h" #include "libc/macros.internal.h" @@ -258,7 +258,10 @@ static textwindows struct HostAdapterInfoNode *appendHostInfo( node->flags = flags; } else { /* Copy from previous node */ - node->flags = parentInfoNode->flags; + if (parentInfoNode) + node->flags = parentInfoNode->flags; + else + node->flags = 0; } ip = ntohl( @@ -508,6 +511,7 @@ static int ioctl_siocgifconf_sysv(int fd, struct ifconf *ifc) { } #pragma GCC push_options #pragma GCC diagnostic ignored "-Walloca-larger-than=" +#pragma GCC diagnostic ignored "-Wanalyzer-out-of-bounds" bufMax = 15000; /* conservative guesstimate */ b = alloca(bufMax); CheckLargeStackAllocation(b, bufMax); diff --git a/libc/calls/mkntenvblock.c b/libc/calls/mkntenvblock.c index ad47b28d2..a6738fa7a 100644 --- a/libc/calls/mkntenvblock.c +++ b/libc/calls/mkntenvblock.c @@ -144,6 +144,7 @@ textwindows int mkntenvblock(char16_t envblock[32767], char *const envp[], n = (CountStrings(envp) + CountStrings(extravars) + 1) * sizeof(char *); #pragma GCC push_options #pragma GCC diagnostic ignored "-Walloca-larger-than=" +#pragma GCC diagnostic ignored "-Wanalyzer-out-of-bounds" env.var = alloca(n); CheckLargeStackAllocation(env.var, n); #pragma GCC pop_options diff --git a/libc/calls/preadv.c b/libc/calls/preadv.c index 83a6f2a86..21ac113e0 100644 --- a/libc/calls/preadv.c +++ b/libc/calls/preadv.c @@ -60,6 +60,7 @@ static ssize_t Preadv(int fd, struct iovec *iov, int iovlen, int64_t off) { struct iovec *iov2; #pragma GCC push_options #pragma GCC diagnostic ignored "-Walloca-larger-than=" +#pragma GCC diagnostic ignored "-Wanalyzer-out-of-bounds" iov2 = alloca(iovlen * sizeof(struct iovec)); CheckLargeStackAllocation(iov2, iovlen * sizeof(struct iovec)); #pragma GCC pop_options diff --git a/libc/calls/pwritev.c b/libc/calls/pwritev.c index d2d8cd043..3373a8f16 100644 --- a/libc/calls/pwritev.c +++ b/libc/calls/pwritev.c @@ -62,6 +62,7 @@ static ssize_t Pwritev(int fd, const struct iovec *iov, int iovlen, struct iovec *iov2; #pragma GCC push_options #pragma GCC diagnostic ignored "-Walloca-larger-than=" +#pragma GCC diagnostic ignored "-Wanalyzer-out-of-bounds" iov2 = alloca(iovlen * sizeof(struct iovec)); CheckLargeStackAllocation(iov2, iovlen * sizeof(struct iovec)); #pragma GCC pop_options diff --git a/libc/calls/readlinkat-nt.c b/libc/calls/readlinkat-nt.c index bd2423272..e57c73a39 100644 --- a/libc/calls/readlinkat-nt.c +++ b/libc/calls/readlinkat-nt.c @@ -52,6 +52,7 @@ static textwindows ssize_t sys_readlinkat_nt_impl(int dirfd, const char *path, ssize_t rc; #pragma GCC push_options #pragma GCC diagnostic ignored "-Walloca-larger-than=" +#pragma GCC diagnostic ignored "-Wanalyzer-out-of-bounds" uint32_t mem = 6000; volatile char *memory = alloca(mem); CheckLargeStackAllocation((char *)memory, mem); diff --git a/libc/calls/readv.c b/libc/calls/readv.c index b48ca2ff6..26d05690f 100644 --- a/libc/calls/readv.c +++ b/libc/calls/readv.c @@ -57,6 +57,7 @@ static ssize_t readv_impl(int fd, const struct iovec *iov, int iovlen) { struct iovec *iov2; #pragma GCC push_options #pragma GCC diagnostic ignored "-Walloca-larger-than=" +#pragma GCC diagnostic ignored "-Wanalyzer-out-of-bounds" iov2 = alloca(iovlen * sizeof(struct iovec)); CheckLargeStackAllocation(iov2, iovlen * sizeof(struct iovec)); #pragma GCC pop_options diff --git a/libc/calls/tinyprint.c b/libc/calls/tinyprint.c index 55aec26ef..2411d9b20 100644 --- a/libc/calls/tinyprint.c +++ b/libc/calls/tinyprint.c @@ -62,6 +62,7 @@ ssize_t tinyprint(int fd, const char *s, ...) { buf[n++] = c; if (n == sizeof(buf)) { if (tinyflush(fd, buf, n, &toto)) { + va_end(va); return toto; } n = 0; diff --git a/libc/calls/ucontext.h b/libc/calls/ucontext.h index b820686bc..b17527c93 100644 --- a/libc/calls/ucontext.h +++ b/libc/calls/ucontext.h @@ -168,8 +168,8 @@ struct ucontext { typedef struct ucontext ucontext_t; -int getcontext(ucontext_t *) dontthrow; -int setcontext(const ucontext_t *) dontthrow; +int getcontext(ucontext_t *) dontthrow __read_write(1); +int setcontext(const ucontext_t *) dontthrow __read_only(1); int swapcontext(ucontext_t *, const ucontext_t *) dontthrow returnstwice; void makecontext(ucontext_t *, void *, int, ...) dontthrow dontcallback; void __sig_restore(const ucontext_t *) wontreturn; diff --git a/libc/calls/writev.c b/libc/calls/writev.c index 7c476d3e5..5e8899e14 100644 --- a/libc/calls/writev.c +++ b/libc/calls/writev.c @@ -57,6 +57,7 @@ static ssize_t writev_impl(int fd, const struct iovec *iov, int iovlen) { struct iovec *iov2; #pragma GCC push_options #pragma GCC diagnostic ignored "-Walloca-larger-than=" +#pragma GCC diagnostic ignored "-Wanalyzer-out-of-bounds" iov2 = alloca(iovlen * sizeof(struct iovec)); CheckLargeStackAllocation(iov2, iovlen * sizeof(struct iovec)); #pragma GCC pop_options diff --git a/libc/integral/c.inc b/libc/integral/c.inc index c3638a08b..0f29ff5f0 100644 --- a/libc/integral/c.inc +++ b/libc/integral/c.inc @@ -367,6 +367,24 @@ typedef struct { #define offsetof(type, member) __builtin_offsetof(type, member) +#if defined(__GNUC__) && __GNUC__ >= 10 +#define __read_only(...) __attribute__((__access__(__read_only__, __VA_ARGS__))) +#define __write_only(...) \ + __attribute__((__access__(__write_only__, __VA_ARGS__))) +#define __read_write(...) \ + __attribute__((__access__(__read_write__, __VA_ARGS__))) +#else +#define __read_only(...) +#define __write_only(...) +#define __read_write(...) +#endif + +#if defined(__GNUC__) && __GNUC__ >= 13 +#define __fd_arg(N) __attribute__((__fd_arg__(N))) +#else +#define __fd_arg(N) +#endif + #ifdef _COSMO_SOURCE #ifndef dontinstrument diff --git a/libc/mem/tinymalloc.inc b/libc/mem/tinymalloc.inc index 1a4527c6b..f726fcd76 100644 --- a/libc/mem/tinymalloc.inc +++ b/libc/mem/tinymalloc.inc @@ -29,6 +29,10 @@ #define TINYMALLOC_MAX_ALIGN sizeof(max_align_t) #endif +#pragma GCC push_options +#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak" +#pragma GCC diagnostic ignored "-Wanalyzer-use-after-free" + static struct { alignas(max_align_t) char bits[TINYMALLOC_MAX_BYTES]; char *memory; @@ -178,3 +182,5 @@ OutOfMemory: errno = ENOMEM; return 0; } + +#pragma GCC pop_options diff --git a/libc/runtime/runtime.h b/libc/runtime/runtime.h index 2492fc95a..ea182a7a5 100644 --- a/libc/runtime/runtime.h +++ b/libc/runtime/runtime.h @@ -4,6 +4,7 @@ COSMOPOLITAN_C_START_ /*───────────────────────────────────────────────────────────────────────────│─╗ │ cosmopolitan § runtime ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ +/* clang-format off */ #ifdef __x86_64__ typedef long jmp_buf[8]; @@ -22,11 +23,9 @@ typedef unsigned long jmp_buf[26]; void mcount(void) libcesque; int daemon(int, int) libcesque; unsigned long getauxval(unsigned long) libcesque; -int setjmp(jmp_buf) -libcesque returnstwice paramsnonnull(); +int setjmp(jmp_buf) libcesque returnstwice paramsnonnull(); void longjmp(jmp_buf, int) libcesque wontreturn paramsnonnull(); -int _setjmp(jmp_buf) -libcesque returnstwice paramsnonnull(); +int _setjmp(jmp_buf) libcesque returnstwice paramsnonnull(); int sigsetjmp(sigjmp_buf, int) libcesque returnstwice paramsnonnull(); void siglongjmp(sigjmp_buf, int) libcesque wontreturn paramsnonnull(); void _longjmp(jmp_buf, int) libcesque wontreturn paramsnonnull(); @@ -37,7 +36,7 @@ void quick_exit(int) wontreturn; void abort(void) wontreturn; int atexit(void (*)(void)) paramsnonnull() libcesque; char *getenv(const char *) paramsnonnull() __wur nosideeffect libcesque; -int putenv(char *) libcesque; +int putenv(char *) libcesque __read_write(1); int setenv(const char *, const char *, int) libcesque; int unsetenv(const char *) libcesque; int clearenv(void) libcesque; @@ -52,8 +51,8 @@ int munlock(const void *, size_t) libcesque; long gethostid(void) libcesque; int sethostid(long) libcesque; char *getlogin(void) libcesque; -int getlogin_r(char *, size_t) libcesque; -int login_tty(int) libcesque; +int getlogin_r(char *, size_t) libcesque __write_only(1, 2); +int login_tty(int) libcesque __fd_arg(1); int getpagesize(void) pureconst libcesque; int getgransize(void) pureconst libcesque; int syncfs(int) dontthrow libcesque; @@ -88,8 +87,8 @@ extern size_t __virtualsize; extern size_t __stackmax; extern bool32 __isworker; /* utilities */ -void _intsort(int *, size_t) libcesque; -void _longsort(long *, size_t) libcesque; +void _intsort(int *, size_t) libcesque __read_write(1, 2); +void _longsort(long *, size_t) libcesque __read_write(1, 2); /* diagnostics */ void ShowCrashReports(void) libcesque; int ftrace_install(void) libcesque; @@ -107,8 +106,8 @@ int __open_executable(void) libcesque; int verynice(void) libcesque; void __warn_if_powersave(void) libcesque; void _Exit1(int) libcesque wontreturn libcesque; -void __paginate(int, const char *) libcesque; -void __paginate_file(int, const char *) libcesque; +void __paginate(int, const char *) libcesque __fd_arg(1); +void __paginate_file(int, const char *) libcesque __fd_arg(1); /* memory management */ void _weakfree(void *) libcesque; void *_mapanon(size_t) attributeallocsize((1)) mallocesque libcesque; diff --git a/libc/sock/sock.h b/libc/sock/sock.h index 43bcf8fb2..64221af63 100644 --- a/libc/sock/sock.h +++ b/libc/sock/sock.h @@ -17,21 +17,22 @@ libcesque uint32_t ntohl(uint32_t) pureconst; #define ntohl(x) __builtin_bswap32(x) #endif +/* clang-format off */ const char *inet_ntop(int, const void *, char *, uint32_t) libcesque; int inet_pton(int, const char *, void *) libcesque; uint32_t inet_addr(const char *) libcesque; libcesque uint32_t *GetHostIps(void) __wur; int socket(int, int, int) libcesque; -int listen(int, int) libcesque; -int shutdown(int, int) libcesque; -ssize_t send(int, const void *, size_t, int) libcesque; -ssize_t recv(int, void *, size_t, int) libcesque; -ssize_t sendfile(int, int, int64_t *, size_t) libcesque; -int getsockopt(int, int, int, void *, uint32_t *) libcesque; -int setsockopt(int, int, int, const void *, uint32_t) libcesque; +int listen(int, int) libcesque __fd_arg(1); +int shutdown(int, int) libcesque __fd_arg(1); +ssize_t send(int, const void *, size_t, int) libcesque __fd_arg(1) __read_only(2, 3); +ssize_t recv(int, void *, size_t, int) libcesque __fd_arg(1) __write_only(2, 3); +ssize_t sendfile(int, int, int64_t *, size_t) libcesque __fd_arg(1) __fd_arg(2) __read_write(3); +int getsockopt(int, int, int, void *, uint32_t *) libcesque __fd_arg(1); +int setsockopt(int, int, int, const void *, uint32_t) libcesque __fd_arg(1); int socketpair(int, int, int, int[2]) libcesque; -int sockatmark(int) libcesque; +int sockatmark(int) libcesque __fd_arg(1); COSMOPOLITAN_C_END_ #endif /* COSMOPOLITAN_LIBC_SOCK_SOCK_H_ */ diff --git a/libc/stdio/freopen.c b/libc/stdio/freopen.c index aabcfa340..6c2902163 100644 --- a/libc/stdio/freopen.c +++ b/libc/stdio/freopen.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" #include "libc/calls/calls.h" #include "libc/stdio/internal.h" #include "libc/stdio/stdio.h" @@ -37,8 +38,8 @@ * @return stream object if successful, or NULL w/ errno */ FILE *freopen(const char *pathname, const char *mode, FILE *stream) { - int fd; FILE *res; + int fd, fd2; unsigned flags; flags = fopenflags(mode); flockfile(stream); @@ -46,19 +47,30 @@ FILE *freopen(const char *pathname, const char *mode, FILE *stream) { if (pathname) { /* open new stream, overwriting existing alloc */ if ((fd = open(pathname, flags, 0666)) != -1) { - dup3(fd, stream->fd, flags & O_CLOEXEC); + fd2 = dup3(fd, stream->fd, flags & O_CLOEXEC); close(fd); - stream->iomode = flags; - stream->beg = 0; - stream->end = 0; - res = stream; + if (fd2 != -1) { + stream->fd = fd2; + stream->iomode = flags; + stream->beg = 0; + stream->end = 0; + res = stream; + } else { + res = NULL; + } } else { res = NULL; } } else { - fcntl(stream->fd, F_SETFD, !!(flags & O_CLOEXEC)); - fcntl(stream->fd, F_SETFL, flags & ~O_CLOEXEC); - res = stream; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wanalyzer-fd-use-without-check" + if (fcntl(stream->fd, F_SETFD, !!(flags & O_CLOEXEC)) != -1 && + fcntl(stream->fd, F_SETFL, flags & ~O_CLOEXEC) != -1) { +#pragma GCC diagnostic pop + res = stream; + } else { + res = NULL; + } } funlockfile(stream); return res; diff --git a/libc/stdio/iconv.c b/libc/stdio/iconv.c index 3b04b6b8d..d565630d3 100644 --- a/libc/stdio/iconv.c +++ b/libc/stdio/iconv.c @@ -1,5 +1,5 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set noet ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ +/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│ +│ vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi │ ╚──────────────────────────────────────────────────────────────────────────────╝ │ │ │ Musl Libc │ @@ -334,6 +334,8 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri case UCS2: case UTF_16: l = 0; + if (!scd) + goto starved; if (!scd->state) { if (*inb < 2) goto starved; c = get_16((void *)*in, 0); @@ -347,6 +349,8 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri continue; case UTF_32: l = 0; + if (!scd) + goto starved; if (!scd->state) { if (*inb < 4) goto starved; c = get_32((void *)*in, 0); @@ -398,6 +402,7 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri if (!c) goto ilseq; break; case ISO2022_JP: + if (!scd) goto starved; if (c >= 128) goto ilseq; if (c == '\033') { l = 3; diff --git a/libc/stdio/nftw.c b/libc/stdio/nftw.c index 53c5ca2da..5bcd8dc06 100644 --- a/libc/stdio/nftw.c +++ b/libc/stdio/nftw.c @@ -102,15 +102,24 @@ static int do_nftw(char *path, dfd = open(path, O_RDONLY | O_DIRECTORY); err = errno; if (dfd < 0 && err == EACCES) type = FTW_DNR; - if (!fd_limit) close(dfd); + if (!fd_limit) { + close(dfd); + dfd = -1; + } } - if (!(flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev))) + if (!(flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev))) { + if (dfd != -1) + close(dfd); return r; + } for (; h; h = h->chain) - if (h->dev == st.st_dev && h->ino == st.st_ino) + if (h->dev == st.st_dev && h->ino == st.st_ino) { + if (dfd != -1) + close(dfd); return 0; + } if ((type == FTW_D || type == FTW_DP) && fd_limit) { if (dfd < 0) { diff --git a/libc/stdio/popen.c b/libc/stdio/popen.c index d53d5a426..a7489d261 100644 --- a/libc/stdio/popen.c +++ b/libc/stdio/popen.c @@ -75,7 +75,10 @@ FILE *popen(const char *cmdline, const char *mode) { if ((f = fdopen(pipefds[dir], mode))) { switch ((pid = fork())) { case 0: +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wanalyzer-fd-leak" unassert(dup2(pipefds[!dir], !dir) == !dir); +#pragma GCC diagnostic pop // we can't rely on cloexec because cocmd builtins don't execve if (pipefds[0] != !dir) unassert(!close(pipefds[0])); diff --git a/libc/stdio/scandir.c b/libc/stdio/scandir.c index e9be6e664..2c1d9811d 100644 --- a/libc/stdio/scandir.c +++ b/libc/stdio/scandir.c @@ -69,7 +69,9 @@ int scandir(const char *path, struct dirent ***res, } errno = old_errno; - if (cmp) qsort(names, cnt, sizeof *names, (int (*)(const void *, const void *))cmp); + if (cmp && names) { + qsort(names, cnt, sizeof *names, (int (*)(const void *, const void *))cmp); + } *res = names; return cnt; } diff --git a/libc/stdio/stdio.h b/libc/stdio/stdio.h index 028c31d3a..8944d949f 100644 --- a/libc/stdio/stdio.h +++ b/libc/stdio/stdio.h @@ -19,6 +19,7 @@ COSMOPOLITAN_C_START_ /*───────────────────────────────────────────────────────────────────────────│─╗ │ cosmopolitan § standard i/o ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ +/* clang-format off */ struct FILE; typedef struct FILE FILE; @@ -27,147 +28,146 @@ extern FILE *stdin; extern FILE *stdout; extern FILE *stderr; -errno_t ferror(FILE *) libcesque paramsnonnull(); -void clearerr(FILE *) libcesque paramsnonnull(); -int feof(FILE *) libcesque paramsnonnull(); -int getc(FILE *) libcesque paramsnonnull(); -int putc(int, FILE *) libcesque paramsnonnull(); -int fflush(FILE *) libcesque; -int fpurge(FILE *) libcesque; -int fgetc(FILE *) libcesque paramsnonnull(); -char *fgetln(FILE *, size_t *) libcesque paramsnonnull((1)); -int ungetc(int, FILE *) libcesque paramsnonnull(); -int fileno(FILE *) libcesque paramsnonnull() nosideeffect; -int fputc(int, FILE *) libcesque paramsnonnull(); -int fputs(const char *, FILE *) libcesque paramsnonnull(); -int fputws(const wchar_t *, FILE *) libcesque paramsnonnull(); -void flockfile(FILE *) libcesque; -void funlockfile(FILE *) libcesque paramsnonnull(); -int ftrylockfile(FILE *) libcesque paramsnonnull(); -char *fgets(char *, int, FILE *) libcesque paramsnonnull(); -wchar_t *fgetws(wchar_t *, int, FILE *) libcesque paramsnonnull(); -wint_t putwc(wchar_t, FILE *) libcesque paramsnonnull(); -wint_t fputwc(wchar_t, FILE *) libcesque paramsnonnull(); +errno_t ferror(FILE *) libcesque paramsnonnull() __read_write(1); +void clearerr(FILE *) libcesque paramsnonnull() __read_write(1); +int feof(FILE *) libcesque paramsnonnull() __read_write(1); +int getc(FILE *) libcesque paramsnonnull() __read_write(1); +int putc(int, FILE *) libcesque paramsnonnull() __read_write(2); +int fflush(FILE *) libcesque __read_write(1); +int fpurge(FILE *) libcesque __read_write(1); +int fgetc(FILE *) libcesque paramsnonnull() __read_write(1); +char *fgetln(FILE *, size_t *) libcesque paramsnonnull((1)) __read_write(1) __write_only(2); +int ungetc(int, FILE *) libcesque paramsnonnull() __write_only(2); +int fileno(FILE *) libcesque paramsnonnull() nosideeffect __write_only(1); +int fputc(int, FILE *) libcesque paramsnonnull() __write_only(2); +int fputs(const char *, FILE *) libcesque paramsnonnull() __write_only(2); +int fputws(const wchar_t *, FILE *) libcesque paramsnonnull() __write_only(2); +void flockfile(FILE *) libcesque __write_only(1); +void funlockfile(FILE *) libcesque paramsnonnull() __write_only(1); +int ftrylockfile(FILE *) libcesque paramsnonnull() __write_only(1); +char *fgets(char *, int, FILE *) libcesque paramsnonnull() __write_only(1, 2) __read_write(3); +wchar_t *fgetws(wchar_t *, int, FILE *) libcesque paramsnonnull() __write_only(1, 2) __read_write(3); +wint_t putwc(wchar_t, FILE *) libcesque paramsnonnull() __write_only(2); +wint_t fputwc(wchar_t, FILE *) libcesque paramsnonnull() __write_only(2); wint_t putwchar(wchar_t) libcesque; wint_t getwchar(void) libcesque; -wint_t getwc(FILE *) libcesque paramsnonnull(); -wint_t fgetwc(FILE *) libcesque paramsnonnull(); -wint_t ungetwc(wint_t, FILE *) libcesque paramsnonnull(); +wint_t getwc(FILE *) libcesque paramsnonnull() __write_only(1); +wint_t fgetwc(FILE *) libcesque paramsnonnull() __write_only(1); +wint_t ungetwc(wint_t, FILE *) libcesque paramsnonnull() __write_only(2); int getchar(void) libcesque; int putchar(int) libcesque; -int puts(const char *) libcesque; -ssize_t getline(char **, size_t *, FILE *) libcesque paramsnonnull(); -ssize_t getdelim(char **, size_t *, int, FILE *) libcesque paramsnonnull(); -FILE *fopen(const char *, const char *) libcesque paramsnonnull((2)) __wur; -FILE *fdopen(int, const char *) libcesque paramsnonnull() __wur; -FILE *fmemopen(void *, size_t, const char *) libcesque paramsnonnull((3)) __wur; -FILE *freopen(const char *, const char *, FILE *) paramsnonnull((2, 3)); -size_t fread(void *, size_t, size_t, FILE *) libcesque paramsnonnull((4)); -size_t fwrite(const void *, size_t, size_t, FILE *) paramsnonnull((4)); -int fclose(FILE *) libcesque; -int fseek(FILE *, long, int) libcesque paramsnonnull(); -long ftell(FILE *) libcesque paramsnonnull(); -int fseeko(FILE *, int64_t, int) libcesque paramsnonnull(); -int64_t ftello(FILE *) libcesque paramsnonnull(); -void rewind(FILE *) libcesque paramsnonnull(); -int fopenflags(const char *) libcesque paramsnonnull(); -void setlinebuf(FILE *) libcesque; -void setbuf(FILE *, char *) libcesque; -void setbuffer(FILE *, char *, size_t) libcesque; -int setvbuf(FILE *, char *, int, size_t) libcesque; -int pclose(FILE *) libcesque; -char *ctermid(char *) libcesque; -void perror(const char *) libcesque relegated; +int puts(const char *) libcesque __read_only(1); + +ssize_t getline(char **, size_t *, FILE *) libcesque paramsnonnull() __read_write(1) __read_write(2) __read_write(3); +ssize_t getdelim(char **, size_t *, int, FILE *) libcesque paramsnonnull() __read_write(1) __read_write(2) __read_write(4); +FILE *fopen(const char *, const char *) libcesque paramsnonnull((2)) __read_only(1) __read_only(2) __wur; +FILE *fdopen(int, const char *) libcesque paramsnonnull() __read_only(2) __wur; +FILE *fmemopen(void *, size_t, const char *) libcesque paramsnonnull((3)) __read_write(1) __read_only(3) __wur; +FILE *freopen(const char *, const char *, FILE *) paramsnonnull((2, 3)) __read_only(1) __read_only(2) __read_write(3); +size_t fread(void *, size_t, size_t, FILE *) libcesque paramsnonnull((4)) __write_only(1) __read_write(4); +size_t fwrite(const void *, size_t, size_t, FILE *) paramsnonnull((4)) __read_only(1) __read_write(4); +int fclose(FILE *) libcesque __read_write(1); +int fseek(FILE *, long, int) libcesque paramsnonnull() __read_write(1); +long ftell(FILE *) libcesque paramsnonnull() __read_write(1); +int fseeko(FILE *, int64_t, int) libcesque paramsnonnull() __read_write(1); +int64_t ftello(FILE *) libcesque paramsnonnull() __read_write(1); +void rewind(FILE *) libcesque paramsnonnull() __read_write(1); +int fopenflags(const char *) libcesque paramsnonnull() __read_only(1); +void setlinebuf(FILE *) libcesque __read_write(1); +void setbuf(FILE *, char *) libcesque __read_write(1) __write_only(2); +void setbuffer(FILE *, char *, size_t) libcesque __read_write(1) __write_only(2); +int setvbuf(FILE *, char *, int, size_t) libcesque __read_write(1); +int pclose(FILE *) libcesque __read_write(1); +char *ctermid(char *) libcesque __write_only(1); +void perror(const char *) libcesque relegated __read_only(1); typedef uint64_t fpos_t; -char *gets(char *) libcesque paramsnonnull(); -int fgetpos(FILE *, fpos_t *) libcesque paramsnonnull(); -int fsetpos(FILE *, const fpos_t *) libcesque paramsnonnull(); +char *gets(char *) libcesque paramsnonnull() __write_only(1); +int fgetpos(FILE *, fpos_t *) libcesque paramsnonnull() __read_write(1) __write_only(2); +int fsetpos(FILE *, const fpos_t *) libcesque paramsnonnull() __read_write(1) __read_only(2); FILE *tmpfile(void) libcesque __wur; -char *tmpnam(char *) libcesque __wur; -char *tmpnam_r(char *) libcesque __wur; +char *tmpnam(char *) libcesque __write_only(1) __wur; +char *tmpnam_r(char *) libcesque __write_only(1) __wur; -FILE *popen(const char *, const char *) libcesque; +FILE *popen(const char *, const char *) libcesque __read_only(1) __read_only(2); /*───────────────────────────────────────────────────────────────────────────│─╗ │ cosmopolitan § standard i/o » formatting ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ -int printf(const char *, ...) printfesque(1) paramsnonnull((1)) libcesque; -int vprintf(const char *, va_list) paramsnonnull() libcesque; -int fprintf(FILE *, const char *, ...) printfesque(2) - paramsnonnull((1, 2)) libcesque; -int vfprintf(FILE *, const char *, va_list) paramsnonnull() libcesque; -int scanf(const char *, ...) libcesque scanfesque(1); -int vscanf(const char *, va_list) libcesque; -int fscanf(FILE *, const char *, ...) libcesque scanfesque(2); -int vfscanf(FILE *, const char *, va_list) libcesque; +int printf(const char *, ...) printfesque(1) paramsnonnull((1)) libcesque __read_only(1); +int vprintf(const char *, va_list) paramsnonnull() libcesque __read_only(1); +int fprintf(FILE *, const char *, ...) printfesque(2) paramsnonnull((1, 2)) libcesque __read_write(1) __read_only(2); +int vfprintf(FILE *, const char *, va_list) paramsnonnull() libcesque __read_write(1) __read_only(2); +int scanf(const char *, ...) libcesque scanfesque(1) __read_only(1); +int vscanf(const char *, va_list) libcesque __read_only(1); +int fscanf(FILE *, const char *, ...) libcesque scanfesque(2) __read_write(1) __read_only(2); +int vfscanf(FILE *, const char *, va_list) libcesque __read_write(1) __read_only(2); -int snprintf(char *, size_t, const char *, ...) printfesque(3) libcesque; -int vsnprintf(char *, size_t, const char *, va_list) libcesque; -int sprintf(char *, const char *, ...) libcesque; -int vsprintf(char *, const char *, va_list) libcesque; +int snprintf(char *, size_t, const char *, ...) printfesque(3) libcesque __write_only(1) __read_only(3); +int vsnprintf(char *, size_t, const char *, va_list) libcesque __write_only(1) __read_only(3); +int sprintf(char *, const char *, ...) libcesque __write_only(1) __read_only(2); +int vsprintf(char *, const char *, va_list) libcesque __write_only(1) __read_only(2); -int fwprintf(FILE *, const wchar_t *, ...) libcesque; -int fwscanf(FILE *, const wchar_t *, ...) libcesque; -int swprintf(wchar_t *, size_t, const wchar_t *, ...) libcesque; -int swscanf(const wchar_t *, const wchar_t *, ...) libcesque; -int vfwprintf(FILE *, const wchar_t *, va_list) libcesque; -int vfwscanf(FILE *, const wchar_t *, va_list) libcesque; -int vswprintf(wchar_t *, size_t, const wchar_t *, va_list) libcesque; -int vswscanf(const wchar_t *, const wchar_t *, va_list) libcesque; -int vwprintf(const wchar_t *, va_list) libcesque; -int vwscanf(const wchar_t *, va_list) libcesque; -int wprintf(const wchar_t *, ...) libcesque; -int wscanf(const wchar_t *, ...) libcesque; -int fwide(FILE *, int) libcesque; +int fwprintf(FILE *, const wchar_t *, ...) libcesque __read_write(1) __read_only(2); +int fwscanf(FILE *, const wchar_t *, ...) libcesque __read_write(1) __read_only(2); +int swprintf(wchar_t *, size_t, const wchar_t *, ...) libcesque __write_only(1) __read_only(3); +int swscanf(const wchar_t *, const wchar_t *, ...) libcesque __read_only(1) __read_only(2); +int vfwprintf(FILE *, const wchar_t *, va_list) libcesque __read_write(1) __read_only(2); +int vfwscanf(FILE *, const wchar_t *, va_list) libcesque __read_write(1) __read_only(2); +int vswprintf(wchar_t *, size_t, const wchar_t *, va_list) libcesque __write_only(1) __read_only(3); +int vswscanf(const wchar_t *, const wchar_t *, va_list) libcesque __read_only(1) __read_only(2); +int vwprintf(const wchar_t *, va_list) libcesque __read_only(1); +int vwscanf(const wchar_t *, va_list) libcesque __read_only(1); +int wprintf(const wchar_t *, ...) libcesque __read_only(1); +int wscanf(const wchar_t *, ...) libcesque __read_only(1); +int fwide(FILE *, int) libcesque __read_write(1); -int sscanf(const char *, const char *, ...) libcesque scanfesque(2); -int vsscanf(const char *, const char *, va_list) libcesque; +int sscanf(const char *, const char *, ...) libcesque scanfesque(2) __read_only(1) __read_only(2); +int vsscanf(const char *, const char *, va_list) libcesque __read_only(1) __read_only(2); /*───────────────────────────────────────────────────────────────────────────│─╗ │ cosmopolitan § standard i/o » allocating ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ -int asprintf(char **, const char *, ...) printfesque(2) - paramsnonnull((1, 2)) libcesque; -int vasprintf(char **, const char *, va_list) paramsnonnull() libcesque; +int asprintf(char **, const char *, ...) printfesque(2) paramsnonnull((1, 2)) libcesque __write_only(1); +int vasprintf(char **, const char *, va_list) paramsnonnull() libcesque __write_only(1); /*───────────────────────────────────────────────────────────────────────────│─╗ │ cosmopolitan § standard i/o » without mutexes ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ -int getc_unlocked(FILE *) libcesque paramsnonnull(); -int puts_unlocked(const char *) libcesque; +int getc_unlocked(FILE *) libcesque paramsnonnull() __read_write(1); +int puts_unlocked(const char *) libcesque __read_only(1); int getchar_unlocked(void) libcesque; -int putc_unlocked(int, FILE *) libcesque paramsnonnull(); +int putc_unlocked(int, FILE *) libcesque paramsnonnull() __read_write(2); int putchar_unlocked(int) libcesque; -void clearerr_unlocked(FILE *) libcesque; -int feof_unlocked(FILE *) libcesque; -int ferror_unlocked(FILE *) libcesque; -int fileno_unlocked(FILE *) libcesque; -int fflush_unlocked(FILE *) libcesque; -int fgetc_unlocked(FILE *) libcesque; -int fputc_unlocked(int, FILE *) libcesque; -size_t fread_unlocked(void *, size_t, size_t, FILE *) libcesque; -size_t fwrite_unlocked(const void *, size_t, size_t, FILE *) libcesque; -char *fgets_unlocked(char *, int, FILE *) libcesque; -int fputs_unlocked(const char *, FILE *) libcesque; -wint_t getwc_unlocked(FILE *) libcesque; +void clearerr_unlocked(FILE *) libcesque __write_only(1); +int feof_unlocked(FILE *) libcesque __read_only(1); +int ferror_unlocked(FILE *) libcesque __read_only(1); +int fileno_unlocked(FILE *) libcesque __read_only(1); +int fflush_unlocked(FILE *) libcesque __read_write(1); +int fgetc_unlocked(FILE *) libcesque __read_write(1); +int fputc_unlocked(int, FILE *) libcesque __read_write(2); +size_t fread_unlocked(void *, size_t, size_t, FILE *) libcesque __write_only(1) __read_write(4); +size_t fwrite_unlocked(const void *, size_t, size_t, FILE *) libcesque __read_only(1) __read_write(4); +char *fgets_unlocked(char *, int, FILE *) libcesque __write_only(1) __read_write(3); +int fputs_unlocked(const char *, FILE *) libcesque __read_only(1) __read_write(2); +wint_t getwc_unlocked(FILE *) libcesque __read_write(1); wint_t getwchar_unlocked(void) libcesque; -wint_t fgetwc_unlocked(FILE *) libcesque; -wint_t fputwc_unlocked(wchar_t, FILE *) libcesque; -wint_t putwc_unlocked(wchar_t, FILE *) libcesque; +wint_t fgetwc_unlocked(FILE *) libcesque __read_write(1); +wint_t fputwc_unlocked(wchar_t, FILE *) libcesque __read_write(2); +wint_t putwc_unlocked(wchar_t, FILE *) libcesque __read_write(2); wint_t putwchar_unlocked(wchar_t) libcesque; -wchar_t *fgetws_unlocked(wchar_t *, int, FILE *) libcesque; -int fputws_unlocked(const wchar_t *, FILE *) libcesque; -wint_t ungetwc_unlocked(wint_t, FILE *) libcesque paramsnonnull(); -int ungetc_unlocked(int, FILE *) libcesque paramsnonnull(); -int fseek_unlocked(FILE *, int64_t, int) libcesque paramsnonnull(); -ssize_t getdelim_unlocked(char **, size_t *, int, FILE *) paramsnonnull(); -int fprintf_unlocked(FILE *, const char *, ...) printfesque(2) libcesque; -int vfprintf_unlocked(FILE *, const char *, va_list) paramsnonnull() libcesque; +wchar_t *fgetws_unlocked(wchar_t *, int, FILE *) libcesque __write_only(1, 2) __read_write(3); +int fputws_unlocked(const wchar_t *, FILE *) libcesque __read_only(1) __read_write(2); +wint_t ungetwc_unlocked(wint_t, FILE *) libcesque paramsnonnull() __read_write(2); +int ungetc_unlocked(int, FILE *) libcesque paramsnonnull() __read_write(2); +int fseek_unlocked(FILE *, int64_t, int) libcesque paramsnonnull() __read_write(1); +ssize_t getdelim_unlocked(char **, size_t *, int, FILE *) paramsnonnull() __read_write(1) __read_write(2) __read_write(4); +int fprintf_unlocked(FILE *, const char *, ...) printfesque(2) libcesque __read_write(1) __read_only(2); +int vfprintf_unlocked(FILE *, const char *, va_list) paramsnonnull() libcesque __read_write(1) __read_only(2); COSMOPOLITAN_C_END_ #endif /* COSMOPOLITAN_LIBC_STDIO_H_ */ diff --git a/libc/stdio/vasprintf.c b/libc/stdio/vasprintf.c index 3f05529d0..907ca8ffa 100644 --- a/libc/stdio/vasprintf.c +++ b/libc/stdio/vasprintf.c @@ -52,6 +52,7 @@ int vasprintf(char **strp, const char *fmt, va_list va) { *strp = p; return rc; } else { + free(p); return -1; } } diff --git a/libc/stdio/vcscanf.c b/libc/stdio/vcscanf.c index ad91f88d8..130670cce 100644 --- a/libc/stdio/vcscanf.c +++ b/libc/stdio/vcscanf.c @@ -254,11 +254,15 @@ int __vcscanf(int callback(void *), // c = READ; } fpbufsize = FP_BUFFER_GROW; - fpbuf = malloc(fpbufsize); - fpbufcur = 0; - fpbuf[fpbufcur++] = c; - fpbuf[fpbufcur] = '\0'; - goto ConsumeFloatingPointNumber; + if ((fpbuf = malloc(fpbufsize))) { + fpbufcur = 0; + fpbuf[fpbufcur++] = c; + fpbuf[fpbufcur] = '\0'; + goto ConsumeFloatingPointNumber; + } else { + items = -1; + goto Done; + } default: items = einval(); goto Done; @@ -513,12 +517,16 @@ int __vcscanf(int callback(void *), // if (discard) { buf = NULL; } else if (ismalloc) { - buf = malloc(bufsize * charbytes); - struct FreeMe *entry; - if (buf && (entry = calloc(1, sizeof(struct FreeMe)))) { - entry->ptr = buf; - entry->next = freeme; - freeme = entry; + if ((buf = malloc(bufsize * charbytes))) { + struct FreeMe *entry; + if (buf && (entry = calloc(1, sizeof(struct FreeMe)))) { + entry->ptr = buf; + entry->next = freeme; + freeme = entry; + } + } else { + items = -1; + goto Done; } } else { buf = va_arg(va, void *); diff --git a/third_party/libcxx/string b/third_party/libcxx/string index 2d5a1154a..b1756794b 100644 --- a/third_party/libcxx/string +++ b/third_party/libcxx/string @@ -10,6 +10,8 @@ #ifndef _LIBCPP_STRING #define _LIBCPP_STRING +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" + // clang-format off /* diff --git a/third_party/libcxxabi/cxa_guard_impl.h b/third_party/libcxxabi/cxa_guard_impl.h index 6a2d25569..568170507 100644 --- a/third_party/libcxxabi/cxa_guard_impl.h +++ b/third_party/libcxxabi/cxa_guard_impl.h @@ -338,7 +338,10 @@ public: return true; if (has_thread_id_support) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" *thread_id_address = current_thread_id.get(); +#pragma GCC diagnostic pop *init_byte_address = PENDING_BIT; return false; diff --git a/tool/build/bigmul.c b/tool/build/bigmul.c index b731d9fc7..332955527 100644 --- a/tool/build/bigmul.c +++ b/tool/build/bigmul.c @@ -48,8 +48,10 @@ void Multiply%dx%d(uint64_t C[%d], const uint64_t A[%d], const uint64_t B[%d]) { uint64_t z,h,l;\n\ uint64_t ", (n + m) * 64, n * 64, m * 64, n + m, n, m, n, m, n + m, n, m); - Rs = gc(calloc(sizeof(*Rs), n + m + 1)); - Ra = gc(calloc(sizeof(*Ra), n + m + 1)); + if (!(Rs = calloc(sizeof(*Rs), n + m + 1))) + __builtin_trap(); + if (!(Ra = calloc(sizeof(*Ra), n + m + 1))) + __builtin_trap(); for (j = 0; j < n; ++j) { if (j) printf(", "); @@ -172,6 +174,8 @@ void Multiply%dx%d(uint64_t C[%d], const uint64_t A[%d], const uint64_t B[%d]) { } printf("}\n"); fflush(stdout); + free(Ra); + free(Rs); } int main(int argc, char *argv[]) { diff --git a/tool/build/dd.c b/tool/build/dd.c index 77c7d6e26..5c5ce461b 100644 --- a/tool/build/dd.c +++ b/tool/build/dd.c @@ -19,6 +19,8 @@ #include "libc/calls/calls.h" #include "libc/fmt/conv.h" #include "libc/limits.h" +#include "libc/mem/gc.h" +#include "libc/mem/mem.h" #include "libc/runtime/runtime.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" @@ -44,8 +46,8 @@ int main(int argc, char *argv[]) { long count = LONG_MAX; long blocksize = 1; int oflags = O_WRONLY | O_TRUNC | O_CREAT; - const char *infile = "/dev/stdin"; - const char *oufile = "/dev/stdout"; + char *infile = gc(strdup("/dev/stdin")); + char *oufile = gc(strdup("/dev/stdout")); prog = argv[0]; if (!prog) diff --git a/tool/build/freebsd2sysv.c b/tool/build/freebsd2sysv.c index a0086c28d..c1e79528d 100644 --- a/tool/build/freebsd2sysv.c +++ b/tool/build/freebsd2sysv.c @@ -25,7 +25,7 @@ #include "libc/sysv/consts/prot.h" int main(int argc, char *argv[]) { - open(argv[1], O_RDWR); - Elf64_Ehdr *e = mmap(0, 64, PROT_READ | PROT_WRITE, MAP_SHARED, 3, 0); + int fd = open(argv[1], O_RDWR); + Elf64_Ehdr *e = mmap(0, 64, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); e->e_ident[EI_OSABI] = ELFOSABI_SYSV; } diff --git a/tool/build/gzip.c b/tool/build/gzip.c index c26d65a73..cb1e1ff13 100644 --- a/tool/build/gzip.c +++ b/tool/build/gzip.c @@ -139,6 +139,7 @@ void Compress(const char *inpath) { FILE *input; gzFile output; int rc, errnum; + FILE *closeme = 0; const char *outpath; char *p, openflags[5]; if ((!inpath || opt_usestdout) && (!isatty(1) || opt_force)) { @@ -151,7 +152,7 @@ void Compress(const char *inpath) { exit(1); } if (inpath) { - input = fopen(inpath, "rb"); + input = closeme = fopen(inpath, "rb"); } else { inpath = "/dev/stdin"; input = stdin; @@ -178,8 +179,9 @@ void Compress(const char *inpath) { } if (!output) { fputs(outpath, stderr); - fputs(": gzopen() failed\n", stderr); - fputs(_strerdoc(errno), stderr); + fputs(": gzopen() failed: ", stderr); + const char *s = _strerdoc(errno); + fputs(s ? s : "EUNKNOWN", stderr); fputs("\n", stderr); exit(1); } @@ -189,7 +191,8 @@ void Compress(const char *inpath) { errnum = 0; fputs(inpath, stderr); fputs(": read failed: ", stderr); - fputs(_strerdoc(ferror(input)), stderr); + const char *s = _strerdoc(ferror(input)); + fputs(s ? s : "EUNKNOWN", stderr); fputs("\n", stderr); _Exit(1); } @@ -201,8 +204,8 @@ void Compress(const char *inpath) { _Exit(1); } } while (rc == sizeof(databuf)); - if (input != stdin) { - if (fclose(input)) { + if (closeme) { + if (fclose(closeme)) { fputs(inpath, stderr); fputs(": close failed\n", stderr); _Exit(1); @@ -221,6 +224,7 @@ void Compress(const char *inpath) { void Decompress(const char *inpath) { FILE *output; gzFile input; + FILE *closeme = 0; int rc, n, errnum; const char *outpath; outpath = 0; @@ -233,8 +237,9 @@ void Decompress(const char *inpath) { } if (!input) { fputs(inpath, stderr); - fputs(": gzopen() failed\n", stderr); - fputs(_strerdoc(errno), stderr); + fputs(": gzopen() failed: ", stderr); + const char *s = _strerdoc(errno); + fputs(s ? s : "EUNKNOWN", stderr); fputs("\n", stderr); exit(1); } @@ -248,10 +253,11 @@ void Decompress(const char *inpath) { memcpy(pathbuf, inpath, n - 3); pathbuf[n - 3] = 0; outpath = pathbuf; - if (!(output = fopen(outpath, opt_append ? "wa" : "wb"))) { + if (!(output = closeme = fopen(outpath, opt_append ? "wa" : "wb"))) { fputs(outpath, stderr); fputs(": open failed: ", stderr); - fputs(_strerdoc(errno), stderr); + const char *s = _strerdoc(errno); + fputs(s ? s : "EUNKNOWN", stderr); fputs("\n", stderr); _Exit(1); } @@ -273,7 +279,8 @@ void Decompress(const char *inpath) { if (fwrite(databuf, rc, 1, output) != 1) { fputs(outpath, stderr); fputs(": write failed: ", stderr); - fputs(_strerdoc(ferror(output)), stderr); + const char *s = _strerdoc(ferror(output)); + fputs(s ? s : "EUNKNOWN", stderr); fputs("\n", stderr); _Exit(1); } @@ -283,8 +290,8 @@ void Decompress(const char *inpath) { fputs(": gzclose failed\n", stderr); _Exit(1); } - if (output != stdout) { - if (fclose(output)) { + if (closeme) { + if (fclose(closeme)) { fputs(outpath, stderr); fputs(": close failed\n", stderr); _Exit(1); diff --git a/tool/build/runit.c b/tool/build/runit.c index 6c2a34fc5..7d2b5346a 100644 --- a/tool/build/runit.c +++ b/tool/build/runit.c @@ -204,7 +204,8 @@ bool Send(int tmpfd, const void *output, size_t outputsize) { static bool once; static z_stream zs; zsize = 32768; - zbuf = gc(malloc(zsize)); + if (!(zbuf = malloc(zsize))) + __builtin_trap(); if (!once) { CHECK_EQ(Z_OK, deflateInit2(&zs, 4, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY)); @@ -226,6 +227,7 @@ bool Send(int tmpfd, const void *output, size_t outputsize) { break; } } while (!zs.avail_out); + free(zbuf); return ok; } diff --git a/tool/emacs/cosmo-c-keywords.el b/tool/emacs/cosmo-c-keywords.el index ff4acc144..e9a29cec5 100644 --- a/tool/emacs/cosmo-c-keywords.el +++ b/tool/emacs/cosmo-c-keywords.el @@ -218,7 +218,20 @@ "__sysv_abi__" "__mode__" "__seg_fs" - "__seg_gs")) + "__seg_gs" + "__access__" + "__read_only__" + "__write_only__" + "__read_write__" + "__read_only" + "__write_only" + "__read_write" + "__fd_arg__" + "__fd_arg" + "__copy__" + "__retain__" + "__tainted_args__" + "__zero_call_used_regs__")) (clang '("__optnone__"