Fix bug with sendfile() on XNU

This commit is contained in:
Justine Tunney 2022-09-13 04:32:29 -07:00
parent 790c661317
commit 827f25f054
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
3 changed files with 26 additions and 12 deletions

View file

@ -37,8 +37,8 @@ ssize_t sys_readv_metal(struct Fd *fd, const struct iovec *iov, int iovlen) {
* escape sequences, in response to requests sent to it via write(). * escape sequences, in response to requests sent to it via write().
* Read & return these if they are available. * Read & return these if they are available.
*/ */
if (_weaken(sys_readv_vga)) { if (weaken(sys_readv_vga)) {
ssize_t res = _weaken(sys_readv_vga)(fd, iov, iovlen); ssize_t res = weaken(sys_readv_vga)(fd, iov, iovlen);
if (res > 0) return res; if (res > 0) return res;
} }
/* fall through */ /* fall through */

View file

@ -23,6 +23,7 @@
#include "libc/calls/syscall-sysv.internal.h" #include "libc/calls/syscall-sysv.internal.h"
#include "libc/calls/syscall_support-nt.internal.h" #include "libc/calls/syscall_support-nt.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/safemacros.internal.h" #include "libc/intrin/safemacros.internal.h"
#include "libc/nt/enum/wait.h" #include "libc/nt/enum/wait.h"
#include "libc/nt/errors.h" #include "libc/nt/errors.h"
@ -106,10 +107,13 @@ static ssize_t sendfile_linux2bsd(int outfd, int infd,
if (IsFreebsd()) { if (IsFreebsd()) {
rc = sys_sendfile_freebsd(infd, outfd, offset, uptobytes, 0, &sbytes, 0); rc = sys_sendfile_freebsd(infd, outfd, offset, uptobytes, 0, &sbytes, 0);
} else { } else {
sbytes = uptobytes;
rc = sys_sendfile_xnu(infd, outfd, offset, &sbytes, 0, 0); rc = sys_sendfile_xnu(infd, outfd, offset, &sbytes, 0, 0);
} }
if (rc != -1) { if (rc != -1) {
if (inout_opt_inoffset) *inout_opt_inoffset += sbytes; if (inout_opt_inoffset) {
*inout_opt_inoffset += sbytes;
}
return sbytes; return sbytes;
} else { } else {
return -1; return -1;
@ -131,15 +135,25 @@ static ssize_t sendfile_linux2bsd(int outfd, int infd,
*/ */
ssize_t sendfile(int outfd, int infd, int64_t *inout_opt_inoffset, ssize_t sendfile(int outfd, int infd, int64_t *inout_opt_inoffset,
size_t uptobytes) { size_t uptobytes) {
if (!uptobytes) return einval(); int rc;
if (uptobytes > 0x7ffffffe /* Microsoft's off-by-one */) return eoverflow(); if (!uptobytes) {
if (IsLinux()) { rc = einval();
return sys_sendfile(outfd, infd, inout_opt_inoffset, uptobytes); } else if (IsAsan() && inout_opt_inoffset &&
!__asan_is_valid(inout_opt_inoffset,
sizeof(*inout_opt_inoffset))) {
rc = efault();
} else if (uptobytes > 0x7ffffffe /* Microsoft's off-by-one */) {
rc = eoverflow();
} else if (IsLinux()) {
rc = sys_sendfile(outfd, infd, inout_opt_inoffset, uptobytes);
} else if (IsFreebsd() || IsXnu()) { } else if (IsFreebsd() || IsXnu()) {
return sendfile_linux2bsd(outfd, infd, inout_opt_inoffset, uptobytes); rc = sendfile_linux2bsd(outfd, infd, inout_opt_inoffset, uptobytes);
} else if (IsWindows()) { } else if (IsWindows()) {
return sendfile_linux2nt(outfd, infd, inout_opt_inoffset, uptobytes); rc = sendfile_linux2nt(outfd, infd, inout_opt_inoffset, uptobytes);
} else { } else {
return copyfd(infd, inout_opt_inoffset, outfd, NULL, uptobytes, 0); rc = copyfd(infd, inout_opt_inoffset, outfd, NULL, uptobytes, 0);
} }
STRACE("sendfile(%d, %d, %p, %'zu) → %ld% m", outfd, infd, inout_opt_inoffset,
uptobytes, rc);
return rc;
} }

View file

@ -637,7 +637,7 @@
(let ((default-directory root)) (let ((default-directory root))
(save-buffer) (save-buffer)
(cond ((memq major-mode '(c-mode c++-mode asm-mode fortran-mode)) (cond ((memq major-mode '(c-mode c++-mode asm-mode fortran-mode))
(let* ((mode (cosmo--make-mode arg "")) (let* ((mode (cosmo--make-mode arg "fastbuild"))
(compile-command (cosmo--compile-command this root 'test mode "" "" ".ok"))) (compile-command (cosmo--compile-command this root 'test mode "" "" ".ok")))
(compile compile-command))) (compile compile-command)))
('t ('t
@ -653,7 +653,7 @@
(let ((default-directory root)) (let ((default-directory root))
(save-buffer) (save-buffer)
(cond ((memq major-mode '(c-mode c++-mode asm-mode fortran-mode)) (cond ((memq major-mode '(c-mode c++-mode asm-mode fortran-mode))
(let* ((mode (cosmo--make-mode arg "")) (let* ((mode (cosmo--make-mode arg "fastbuild"))
(compile-command (cosmo--compile-command this root 'run-win10 mode "" "" ""))) (compile-command (cosmo--compile-command this root 'run-win10 mode "" "" "")))
(compile compile-command))) (compile compile-command)))
('t ('t