Skip to content

Commit

Permalink
Fix some bugs with dup2() and ZipOS
Browse files Browse the repository at this point in the history
On UNIX if dup2(newfd) was a ZipOS file descriptor, then its resources
weren't being released, and the newly created file descriptor would be
mistaken for ZipOS due to its memory not being cleared. On Windows, an
issue also existed relating to newfd resources not being released.
  • Loading branch information
jart committed Nov 30, 2023
1 parent 26c70e0 commit 4b7ba9a
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 3 deletions.
8 changes: 7 additions & 1 deletion libc/calls/dup-nt.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@
#include "libc/calls/struct/sigset.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/weaken.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/sock/internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/o.h"
Expand Down Expand Up @@ -57,7 +59,11 @@ static textwindows int sys_dup_nt_impl(int oldfd, int newfd, int flags,
return -1;
}
if (g_fds.p[newfd].kind) {
sys_close_nt(newfd, newfd);
if (g_fds.p[newfd].kind == kFdZip) {
_weaken(__zipos_close)(newfd);
} else {
sys_close_nt(newfd, newfd);
}
}
}

Expand Down
8 changes: 8 additions & 0 deletions libc/calls/dup2.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,15 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"

/**
Expand Down Expand Up @@ -74,6 +77,11 @@ int dup2(int oldfd, int newfd) {
#endif
} else if (!IsWindows()) {
rc = sys_dup2(oldfd, newfd, 0);
if (rc != -1 && oldfd != newfd && __isfdkind(newfd, kFdZip) && !__vforked) {
_weaken(__zipos_free)(
(struct ZiposHandle *)(intptr_t)g_fds.p[newfd].handle);
bzero(g_fds.p + newfd, sizeof(*g_fds.p));
}
} else if (newfd < 0) {
rc = ebadf();
} else if (oldfd == newfd) {
Expand Down
8 changes: 8 additions & 0 deletions libc/calls/dup3.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,15 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"

Expand Down Expand Up @@ -71,6 +74,11 @@ int dup3(int oldfd, int newfd, int flags) {
rc = enotsup();
} else if (!IsWindows()) {
rc = sys_dup3(oldfd, newfd, flags);
if (rc != -1 && __isfdkind(newfd, kFdZip) && !__vforked) {
_weaken(__zipos_free)(
(struct ZiposHandle *)(intptr_t)g_fds.p[newfd].handle);
bzero(g_fds.p + newfd, sizeof(*g_fds.p));
}
} else {
rc = sys_dup_nt(oldfd, newfd, flags, -1);
}
Expand Down
15 changes: 13 additions & 2 deletions test/libc/calls/dup_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
#include "libc/testlib/testlib.h"
#include "libc/x/xspawn.h"

__static_yoink("libc/testlib/hyperion.txt");

void SetUpOnce(void) {
testlib_enable_tmp_setup_teardown();
}
Expand All @@ -50,7 +52,6 @@ static textstartup void TestInit(int argc, char **argv) {

const void *const TestCtor[] initarray = {TestInit};

#if 0
TEST(dup, ebadf) {
ASSERT_SYS(EBADF, -1, dup(-1));
ASSERT_SYS(EBADF, -1, dup2(-1, 0));
Expand All @@ -72,7 +73,17 @@ TEST(dup, bigNumber) {
ASSERT_SYS(0, 100, dup2(0, 100));
ASSERT_SYS(0, 0, close(100));
}
#endif

TEST(dup2, zipos) {
ASSERT_SYS(0, 3, creat("real", 0644));
ASSERT_SYS(0, 4, open("/zip/libc/testlib/hyperion.txt", O_RDONLY));
ASSERT_SYS(0, 2, write(3, "hi", 2));
ASSERT_SYS(EBADF, -1, write(4, "hi", 2));
ASSERT_SYS(0, 4, dup2(3, 4));
ASSERT_SYS(0, 2, write(4, "hi", 2));
ASSERT_SYS(0, 0, close(4));
ASSERT_SYS(0, 0, close(3));
}

#ifdef __x86_64__
TEST(dup, clearsCloexecFlag) {
Expand Down

0 comments on commit 4b7ba9a

Please sign in to comment.