mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-28 00:02:28 +00:00
Make fixes and improvements
- Invent iso8601us() for faster timestamps - Improve --strace descriptions of sigset_t - Rebuild the Landlock Make bootstrap binary - Introduce MODE=sysv for non-Windows builds - Permit OFD fcntl() locks under pledge(flock) - redbean can now protect your kernel from ddos - Have vfork() fallback to sys_fork() not fork() - Change kmalloc() to not die when out of memory - Improve documentation for some termios functions - Rewrite putenv() and friends to conform to POSIX - Fix linenoise + strace verbosity issue on Windows - Fix regressions in our ability to show backtraces - Change redbean SetHeader() to no-op if value is nil - Improve fcntl() so SQLite locks work in non-WAL mode - Remove some unnecessary work during fork() on Windows - Create redbean-based SSL reverse proxy for IPv4 TurfWar - Fix ape/apeinstall.sh warning when using non-bash shells - Add ProgramTrustedIp(), and IsTrustedIp() APIs to redbean - Support $PWD, $UID, $GID, and $EUID in command interpreter - Introduce experimental JTqFpD APE prefix for non-Windows builds - Invent blackhole daemon for firewalling IP addresses via UNIX named socket - Add ProgramTokenBucket(), AcquireToken(), and CountTokens() APIs to redbean
This commit is contained in:
parent
648bf6555c
commit
f7ff77d865
209 changed files with 3818 additions and 998 deletions
|
@ -36,7 +36,7 @@ void SetUpOnce(void) {
|
|||
|
||||
TEST(access, efault) {
|
||||
ASSERT_SYS(EFAULT, -1, access(0, F_OK));
|
||||
if (IsWindows() && !IsAsan()) return; // not possible
|
||||
if (IsWindows() || !IsAsan()) return; // not possible
|
||||
ASSERT_SYS(EFAULT, -1, access((void *)77, F_OK));
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ void SetUpOnce(void) {
|
|||
|
||||
TEST(chdir, efault) {
|
||||
ASSERT_SYS(EFAULT, -1, chdir(0));
|
||||
if (IsWindows() && !IsAsan()) return; // not possible
|
||||
if (IsWindows() || !IsAsan()) return; // not possible
|
||||
ASSERT_SYS(EFAULT, -1, chdir((void *)77));
|
||||
}
|
||||
|
||||
|
|
168
test/libc/calls/lock2_test.c
Normal file
168
test/libc/calls/lock2_test.c
Normal file
|
@ -0,0 +1,168 @@
|
|||
/*-*- 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 2022 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"
|
||||
#include "libc/calls/struct/flock.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/testlib/subprocess.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
char testlib_enable_tmp_setup_teardown;
|
||||
|
||||
TEST(lock, wholeFile) {
|
||||
char buf[512];
|
||||
ASSERT_SYS(0, 3, open("db", O_RDWR | O_CREAT | O_EXCL, 0644));
|
||||
ASSERT_SYS(0, 0, fcntl(3, F_SETLK, &(struct flock){.l_type = F_RDLCK}));
|
||||
ASSERT_SYS(0, 0, fcntl(3, F_SETLK, &(struct flock){.l_type = F_UNLCK}));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(lock, testUpgradeFromReadToWriteLock) {
|
||||
char buf[512];
|
||||
ASSERT_SYS(0, 3, open("db", O_RDWR | O_CREAT | O_EXCL, 0644));
|
||||
ASSERT_SYS(0, 0,
|
||||
fcntl(3, F_SETLK,
|
||||
&(struct flock){
|
||||
.l_type = F_RDLCK,
|
||||
.l_start = 0x40000000,
|
||||
.l_len = 1,
|
||||
}));
|
||||
ASSERT_SYS(0, 0,
|
||||
fcntl(3, F_SETLK,
|
||||
&(struct flock){
|
||||
.l_type = F_WRLCK,
|
||||
.l_start = 0x40000000,
|
||||
.l_len = 1,
|
||||
}));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(lock, testUpgradeWriteToWriteLock) {
|
||||
char buf[512];
|
||||
ASSERT_SYS(0, 3, open("db", O_RDWR | O_CREAT | O_EXCL, 0644));
|
||||
ASSERT_SYS(0, 0,
|
||||
fcntl(3, F_SETLK,
|
||||
&(struct flock){
|
||||
.l_type = F_WRLCK,
|
||||
.l_start = 0x40000000,
|
||||
.l_len = 1,
|
||||
}));
|
||||
ASSERT_SYS(0, 0,
|
||||
fcntl(3, F_SETLK,
|
||||
&(struct flock){
|
||||
.l_type = F_WRLCK,
|
||||
.l_start = 0x40000000,
|
||||
.l_len = 1,
|
||||
}));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(lock, unlockEverything_unlocksSmallerRanges) {
|
||||
int fd, pi[2];
|
||||
char buf[8] = {0};
|
||||
ASSERT_SYS(0, 3, creat("db", 0644));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
ASSERT_SYS(0, 0, pipe(pi));
|
||||
SPAWN(fork);
|
||||
ASSERT_SYS(0, 5, open("db", O_RDWR));
|
||||
ASSERT_SYS(0, 0, close(4));
|
||||
ASSERT_SYS(0, 8, read(3, buf, 8));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
ASSERT_SYS(0, 0,
|
||||
fcntl(5, F_SETLK,
|
||||
&(struct flock){
|
||||
.l_type = F_WRLCK,
|
||||
.l_start = 0x40000000,
|
||||
.l_len = 1,
|
||||
}));
|
||||
ASSERT_SYS(0, 0,
|
||||
fcntl(5, F_SETLK,
|
||||
&(struct flock){
|
||||
.l_type = F_WRLCK,
|
||||
.l_start = 0x40000005,
|
||||
.l_len = 1,
|
||||
}));
|
||||
ASSERT_SYS(0, 0, close(5));
|
||||
PARENT();
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
ASSERT_NE(-1, (fd = open("db", O_RDWR)));
|
||||
ASSERT_SYS(0, 0,
|
||||
fcntl(fd, F_SETLK,
|
||||
&(struct flock){
|
||||
.l_type = F_WRLCK,
|
||||
.l_start = 0x40000000,
|
||||
.l_len = 1,
|
||||
}));
|
||||
ASSERT_SYS(0, 0,
|
||||
fcntl(fd, F_SETLK,
|
||||
&(struct flock){
|
||||
.l_type = F_WRLCK,
|
||||
.l_start = 0x40000005,
|
||||
.l_len = 1,
|
||||
}));
|
||||
ASSERT_SYS(0, 0,
|
||||
fcntl(fd, F_SETLK,
|
||||
&(struct flock){
|
||||
.l_type = F_UNLCK,
|
||||
}));
|
||||
ASSERT_SYS(0, 8, write(4, buf, 8));
|
||||
ASSERT_SYS(0, 0, close(4));
|
||||
WAIT(exit, 0);
|
||||
ASSERT_SYS(0, 0, close(fd));
|
||||
}
|
||||
|
||||
TEST(lock, close_releasesLocks) {
|
||||
int fd, pi[2];
|
||||
char buf[8] = {0};
|
||||
ASSERT_SYS(0, 3, creat("db", 0644));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
ASSERT_SYS(0, 0, pipe(pi));
|
||||
SPAWN(fork);
|
||||
ASSERT_SYS(0, 5, open("db", O_RDWR));
|
||||
ASSERT_SYS(0, 0, close(4));
|
||||
ASSERT_SYS(0, 8, read(3, buf, 8));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
ASSERT_SYS(0, 0,
|
||||
fcntl(5, F_SETLK,
|
||||
&(struct flock){
|
||||
.l_type = F_WRLCK,
|
||||
.l_start = 0x40000000,
|
||||
.l_len = 1,
|
||||
}));
|
||||
ASSERT_SYS(0, 0, close(5));
|
||||
PARENT();
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
ASSERT_NE(-1, (fd = open("db", O_RDWR)));
|
||||
ASSERT_SYS(0, 0,
|
||||
fcntl(fd, F_SETLK,
|
||||
&(struct flock){
|
||||
.l_type = F_WRLCK,
|
||||
.l_start = 0x40000000,
|
||||
.l_len = 1,
|
||||
}));
|
||||
ASSERT_SYS(0, 0, close(fd));
|
||||
ASSERT_SYS(0, 8, write(4, buf, 8));
|
||||
ASSERT_SYS(0, 0, close(4));
|
||||
WAIT(exit, 0);
|
||||
}
|
207
test/libc/calls/lock_ofd_test.c
Normal file
207
test/libc/calls/lock_ofd_test.c
Normal file
|
@ -0,0 +1,207 @@
|
|||
/*-*- 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 2022 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"
|
||||
#include "libc/calls/struct/flock.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Better Advisory Locks Test
|
||||
*/
|
||||
|
||||
#define PROCESSES 8
|
||||
#define THREADS 8 // <-- THIS
|
||||
#define RATIO 3
|
||||
#define ITERATIONS 10
|
||||
|
||||
char testlib_enable_tmp_setup_teardown;
|
||||
|
||||
_Thread_local const char *kind;
|
||||
|
||||
bool SupportsOfdLocks(void) {
|
||||
int e;
|
||||
bool r;
|
||||
if (!IsLinux()) return false;
|
||||
// F_OFD_* was introduced in linux 3.15
|
||||
// getrandom() was introduced in linux 3.17
|
||||
// testing for getrandom() should be a sure thing w/o creating an fd
|
||||
e = errno;
|
||||
r = !sys_getrandom(0, 0, 0);
|
||||
errno = e;
|
||||
return r;
|
||||
}
|
||||
|
||||
void SetUp(void) {
|
||||
if (!SupportsOfdLocks()) {
|
||||
kprintf("ofd locks not supported on this system\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
void Log(const char *fmt, ...) {
|
||||
#if 0
|
||||
va_list va;
|
||||
char b[512];
|
||||
int i, n = sizeof(b);
|
||||
va_start(va, fmt);
|
||||
i = ksnprintf(b, n, "%s pid=%d tid=%d ", kind, getpid(), gettid());
|
||||
i += kvsnprintf(b + i, MAX(0, n - i), fmt, va);
|
||||
i += ksnprintf(b + i, MAX(0, n - i), "\n");
|
||||
write(2, b, MIN(i, n));
|
||||
va_end(va);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Lock(int fd, int type, long start, long len) {
|
||||
int e;
|
||||
struct flock lock = {
|
||||
.l_type = type,
|
||||
.l_whence = SEEK_SET,
|
||||
.l_start = start,
|
||||
.l_len = len,
|
||||
};
|
||||
e = errno;
|
||||
while (fcntl(fd, F_OFD_SETLK, &lock)) {
|
||||
ASSERT_TRUE(errno == EAGAIN || errno == EACCES);
|
||||
errno = e;
|
||||
Log("flock spinning on %d", fd);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteLock(int fd, long start, long len) {
|
||||
Lock(fd, F_WRLCK, start, len);
|
||||
Log("acquired write lock on %d", fd);
|
||||
}
|
||||
|
||||
void ReadLock(int fd, long start, long len) {
|
||||
Lock(fd, F_RDLCK, start, len);
|
||||
Log("acquired read lock on %d", fd);
|
||||
}
|
||||
|
||||
void Unlock(int fd, long start, long len) {
|
||||
Lock(fd, F_UNLCK, start, len);
|
||||
Log("released lock on %d", fd);
|
||||
}
|
||||
|
||||
void *Reader(void *arg) {
|
||||
int i, j, fd;
|
||||
char buf[10];
|
||||
kind = arg;
|
||||
ASSERT_NE(-1, (fd = open("db", O_RDONLY)));
|
||||
for (j = 0; j < ITERATIONS; ++j) {
|
||||
ReadLock(fd, 10, 10);
|
||||
for (i = 0; i < 10; ++i) {
|
||||
ASSERT_SYS(0, 1, pread(fd, buf + i, 1, 10 + i));
|
||||
ASSERT_EQ(buf[0], buf[i]);
|
||||
}
|
||||
Unlock(fd, 10, 10);
|
||||
sched_yield();
|
||||
}
|
||||
ASSERT_SYS(0, 0, close(fd));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *Writer(void *arg) {
|
||||
int i, j, fd;
|
||||
char buf[10];
|
||||
kind = arg;
|
||||
ASSERT_NE(-1, (fd = open("db", O_RDWR)));
|
||||
for (j = 0; j < ITERATIONS; ++j) {
|
||||
WriteLock(fd, 10, 10);
|
||||
for (i = 0; i < 10; ++i) {
|
||||
ASSERT_SYS(0, 1, pread(fd, buf + i, 1, 10 + i));
|
||||
ASSERT_EQ(buf[0], buf[i]);
|
||||
}
|
||||
for (i = 0; i < 10; ++i) {
|
||||
buf[i]++;
|
||||
}
|
||||
for (i = 0; i < 10; ++i) {
|
||||
ASSERT_SYS(0, 1, pwrite(fd, buf + i, 1, 10 + i));
|
||||
}
|
||||
Unlock(fd, 10, 10);
|
||||
sched_yield();
|
||||
}
|
||||
ASSERT_SYS(0, 0, close(fd));
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST(posixAdvisoryLocks, threadsAndProcessesFightingForLock) {
|
||||
int i, rc, pid, fd, ws;
|
||||
pthread_t th[THREADS + 1];
|
||||
|
||||
ASSERT_SYS(0, 3, creat("db", 0644));
|
||||
ASSERT_SYS(0, 0, ftruncate(3, 30));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
|
||||
for (i = 0; i < THREADS; ++i) {
|
||||
if (i % RATIO == 0) {
|
||||
ASSERT_EQ(0, pthread_create(th + i, 0, Reader, "reader thread"));
|
||||
} else {
|
||||
ASSERT_EQ(0, pthread_create(th + i, 0, Writer, "writer thread"));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < PROCESSES; ++i) {
|
||||
ASSERT_NE(-1, (rc = fork()));
|
||||
if (!rc) {
|
||||
if (i % RATIO == 0) {
|
||||
Writer("writer process");
|
||||
} else {
|
||||
Reader("reader process");
|
||||
}
|
||||
_Exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_NE(-1, (fd = open("db", O_RDWR)));
|
||||
Lock(fd, F_WRLCK, 0, 10);
|
||||
Lock(fd, F_WRLCK, 20, 10);
|
||||
|
||||
for (i = 0; i < THREADS; ++i) {
|
||||
ASSERT_EQ(0, pthread_join(th[i], 0));
|
||||
}
|
||||
|
||||
kind = "main process";
|
||||
for (;;) {
|
||||
int e = errno;
|
||||
if ((pid = waitpid(0, &ws, 0)) != -1) {
|
||||
if (WIFSIGNALED(ws)) {
|
||||
Log("process %d terminated with %G", pid, WTERMSIG(ws));
|
||||
testlib_incrementfailed();
|
||||
} else if (WEXITSTATUS(ws)) {
|
||||
Log("process %d exited with %d", pid, WEXITSTATUS(ws));
|
||||
testlib_incrementfailed();
|
||||
}
|
||||
} else {
|
||||
ASSERT_EQ(ECHILD, errno);
|
||||
errno = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_SYS(0, 0, close(fd));
|
||||
}
|
|
@ -33,7 +33,7 @@
|
|||
*/
|
||||
|
||||
#define PROCESSES 8
|
||||
#define THREADS (IsWindows() ? 8 : 0)
|
||||
#define THREADS 0 // <-- consider F_OFD_* locks
|
||||
#define RATIO 3
|
||||
#define ITERATIONS 10
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ void SetUpOnce(void) {
|
|||
|
||||
TEST(open, efault) {
|
||||
ASSERT_SYS(EFAULT, -1, open(0, O_RDONLY));
|
||||
if (IsWindows() && !IsAsan()) return; // not possible
|
||||
if (IsWindows() || !IsAsan()) return; // not possible
|
||||
ASSERT_SYS(EFAULT, -1, open((void *)77, O_RDONLY));
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/calls/struct/rusage.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
|
@ -175,3 +176,27 @@ TEST(sigaction, ignoringSignalDiscardsSignal) {
|
|||
ASSERT_EQ(0, sigprocmask(SIG_UNBLOCK, &blocked, NULL));
|
||||
EXPECT_EQ(0, OnSignalCnt);
|
||||
}
|
||||
|
||||
TEST(sigaction, autoZombieSlayer) {
|
||||
if (IsWindows()) return;
|
||||
int pid;
|
||||
struct sigaction sa;
|
||||
// make sure we're starting in expected state
|
||||
ASSERT_SYS(0, 0, sigaction(SIGCHLD, 0, &sa));
|
||||
ASSERT_EQ(SIG_DFL, sa.sa_handler);
|
||||
// verify child becomes zombie
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) _Exit(0);
|
||||
ASSERT_SYS(0, pid, wait(0));
|
||||
// enable automatic zombie slayer
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sa.sa_flags = SA_NOCLDWAIT; // seems to be optional
|
||||
sigemptyset(&sa.sa_mask);
|
||||
ASSERT_SYS(0, 0, sigaction(SIGCHLD, &sa, &sa));
|
||||
// verify it works
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) _Exit(0);
|
||||
ASSERT_SYS(ECHILD, -1, wait(0));
|
||||
// clean up
|
||||
ASSERT_SYS(0, 0, sigaction(SIGCHLD, &sa, 0));
|
||||
}
|
||||
|
|
|
@ -117,6 +117,12 @@ o/$(MODE)/test/libc/calls/fcntl_test.com.runs: \
|
|||
o/$(MODE)/test/libc/calls/lock_test.com.runs: \
|
||||
private .PLEDGE = stdio rpath wpath cpath fattr proc flock
|
||||
|
||||
o/$(MODE)/test/libc/calls/lock2_test.com.runs: \
|
||||
private .PLEDGE = stdio rpath wpath cpath fattr proc flock
|
||||
|
||||
o/$(MODE)/test/libc/calls/lock_ofd_test.com.runs: \
|
||||
private .PLEDGE = stdio rpath wpath cpath fattr proc flock
|
||||
|
||||
o/$(MODE)/test/libc/calls/openbsd_test.com.runs: \
|
||||
private .PLEDGE = stdio rpath wpath cpath fattr proc unveil
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ void SetUpOnce(void) {
|
|||
|
||||
TEST(unlink, efault) {
|
||||
ASSERT_SYS(EFAULT, -1, unlink(0));
|
||||
if (IsWindows() && !IsAsan()) return; // not possible
|
||||
if (IsWindows() || !IsAsan()) return; // not possible
|
||||
ASSERT_SYS(EFAULT, -1, unlink((void *)77));
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue