some users of libuv rely on uv_exepath to be an actual path to a
program. unfortunately, the OpenBSD KERN_PROC_ARGV sysctl just returns
what is in argv[0], so if the program was executed by being looked up in
$PATH, uv_exepath would only return the basename and not an actual path.
to fix, this use the same approach as IBM i, OS/390 and AIX by searching
with uv__search_path. this is also the same approach the Zig language
has taken for the similar selfExePath function for OpenBSD.
the tests expect that uv_exepath still works after uv_set_process_title,
which on BSD is a call to setproctitle. the place setproctitle stores to
is the same place that KERN_PROC_ARGV reads from, so we need to stash
the original argv[0] in uv_setup_args to recover it later in uv_exepath.
0x10FFFF is the valid max unicode character, so the check should be
inclusive.
This assert gets triggered because uv__wtf8_decode1 (used by
uv_wtf8_length_as_utf16) has the correct code_point <= 0x10FFFF check,
so the sequence is treated as valid and it will be passed into
uv_wtf8_to_utf16, where the incorrect assert gets triggered:
src/idna.c:397: uv_wtf8_to_utf16: Assertion `code_point < 0x10FFFF' failed.
Accomplish this by replacing `GetDiskFreeSpaceW()` with
`NtQueryVolumeInformationFile()` which allows us to represent blocks
larger than 2^32 - 1 via
`FILE_FS_FULL_SIZE_INFORMATION.TotalAllocationUnits`.
Expanded `fs_statfs` test to check that `uv_fs_statfs()` also works with
files, meaning https://github.com/libuv/libuv/issues/2683 remains fixed
without the need of https://github.com/libuv/libuv/pull/2695.
It was reported that PTYs on Linux sometimes report POLLHUP, return a
partial read, but still return more data on the next read.
Libuv contains an optimization where it assumes a partial read after
POLLHUP means the next read can be skipped because it's going to fail
with EOF anyway. That assumption was thought to be always true but,
alas, it isn't.
The fact the optimization has been present for 13 years and this is the
first bug report about it, indicates how rare this particular condition
is, but of course we can't skim on correctness.
The reworked optimization only uses POLLHUP as an input signal when
POLLIN is not also set. That means we no longer have to track partial
reads because we're going to try and read anyway as long as POLLIN is
set. It seems to cause no measurable regressions on the test suite or
the (lightly tested) benchmarks.
Fixes: https://github.com/libuv/libuv/issues/4992
If uv_spawn() fails after uv__handle_init() has been called, the handle
remains in loop->handle_queue. This causes use-after-free if the handle
is stack-allocated or freed, and a subsequent loop operation like
uv_walk() accesses it.
This follows the same pattern as uv_tcp_init_ex() which explicitly
removes the handle from the queue on error.
The initial FindFirstFile can fail with ERROR_FILE_NOT_FOUND, meaning
no matches (read: empty directory), which leaves dir_handle set to
INVALID_HANDLE_VALUE. Not an actual error, it just means no results.
I can't get FindFirstFile to work like that on regular file systems
but it's been reported that it does under sshfs-win and the MSDN
documentation clearly states it's possible. Handle it.
Fixes: https://github.com/libuv/libuv/issues/4952
Remove the microsecond truncation in uv__fs_to_timespec() function to enable
full nanosecond resolution support. The utimensat() system call already
supports nanosecond precision, so the artificial truncation to microseconds
is no longer necessary.
This allows file modification and access times to be set with full nanosecond
precision instead of being limited to microsecond resolution.
Fixes the TODO comment about removing the microsecond resolution limit.
Fetch file metadata by handle instead of by path, otherwise there is a
race window between fetching and acting on said metadata where another
process can replace the file with another one.
There is still a potential race when upgrading the short path to a long
path but that that one is intrinsic. It's not something libuv can solve
except by refraining from calling GetLongPathName.
Fixes: https://github.com/libuv/libuv/issues/4568
The `flags` argument to `uv__udp_recvmsg_errqueue` was not initialized
in all code paths. Shuffle code around to make the control flow more
obvious (at the cost of a less legible diff.)
Also fixes an unused label warning when building on systems that aren't
Linux.
Introduced last month in commit 80a5e3ba0, "linux: add MSG_ERRQUEUE
ipv4/ipv6 udp support".
Add a stub function for no-ahafs builds. src/unix/core.c won't actually
call uv__ahafs_event but the linker still needs to see a symbol.
Like commit 87943b03 but for IBM i instead of AIX this time.
While unlikely that this fails (since it is implemented to call
`abort()` instead of actually return an error code, we would
theoretically leak this state. The process state init doesn't actually
have a cleanup, and just awkwardly relies on uv_signal_close being
unnecessary (which is likely true though).
_snwprintf_s takes its length argument in characters, not bytes.
Does not appear to be a security issue because the paths are not under
an attacker's control unless the system has been compromised beyond
salvation: requires a combination of being able to set the name of the
executable and/or changing %LOCALAPPDATA% or a registry key.
Refs: https://github.com/libuv/libuv/security/advisories/GHSA-jjrx-vr7q-7732
The static initial table reserved space for MxN elements but only used
every Nth element. Removing the excess elements shrinks the table 16x.
I added search/insertion/deletion time logging while here to ensure no
performance regressions.
Fixes: https://github.com/libuv/libuv/issues/4823
Rationale for changing it to an enum:
- frees up some bits that can be used for other things
- is potentially faster (direct vs. indirect call)
- is potentially more secure (makes UAF or overruns harder to exploit,
no arbitrary function pointer to clobber)
Fixes: https://github.com/libuv/libuv/issues/4842
The AArch64 YIELD instruction affects processors that support
symmetric multithreading, while on other implementations (which
are the majority on the market) it is equivalent to NOP, thus
failing to achieve the desired delay effect inside uv__async_spin().
Instead, use the ISB instruction, following one of Arm's
recommendations [1].
[1] https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/multi-threaded-applications-arm
Signed-off-by: Anton Kirilov <anton.kirilov@arm.com>
This apparently manifests when one passes `--cpu=.5` to docker because
then /sys/fs/cgroup/cpu.max looks like `50000 100000`, and 50000 divided
by 100000 is zero when using integer math.
Return 1 in that case, indicating there is at least one CPU available.
Returning 0 makes no sense because there is always at least one CPU
available, otherwise the program wouldn't be running.
Fixes: https://github.com/nodejs/node/issues/59200
Fix a logic bug in the fallback code for platforms that don't have a
sendmmsg-like system call. It only sent at most one packet, even when
there were more available, and that was observable through a failing
test on such systems.
Fixes: https://github.com/libuv/libuv/issues/4848
Wine has a bug (https://bugs.winehq.org/show_bug.cgi?id=50771) where
FILE_WRITE_ATTRIBUTES will cause CreateFile to fail if the file is
read-only. The recommended work around is to instead use
FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE, which we do as of #4318.
However, we were still using FILE_WRITE_ATTRIBUTES to create the
initial handle, despite this no longer being required, except for
the fallback path. As a result, libuv is still broken under wine,
even on master. Fix this by removing the `FILE_WRITE_ATTRIBUTES`
from the initial CreateFile call and re-opening the handle in the
fallback path if necessary. Note that we still have the same issue
in fs_chmod and I've requested some guidance from wine on what
to do about this, but this should at least fix unlink.
Refs: https://github.com/JuliaLang/julia/issues/58980
Starting a new read after uv_read_cb returns causes memory corruption on
the OVERLAPPED read_req if uv_read_stop+uv_read_start was called during
the callback after the latest refactoring. This apparently also forces
the kernel to deadlock us, since it apparently cannot cancel the second
read while the first one is pending (reads apparently are not permitted
to finish out of order). Avoid that simply by not issuing another read
(set more=0) if there is already a read pending (from uv_read_start).
There are probably better things we could do here (such as bring back
`uv_active_tcp_streams_threshold`), but the current `alloc_cb` design
may not currently permit that without making breaking changes. We could
also detect in `uv_read_start` that we are inside of of the `read_cb`
for that stream, and defer the actual zero-read until the read_cb
returns, but that would likely be a larger change.
Fix#4738
Large-ish functions with many call sites in different translation units
should not be `static inline`, that just results in lots of code
duplication which the linker may or may not deduplicate. When it does,
the linker has to do extra work; when it doesn't, binaries get bigger.
Refs: https://github.com/libuv/libuv/issues/4819
Commit 7fb43d3c from August 2012 moved uv__atomic_exchange_set from
async.c into a header file but in all those years, nothing except
async.c has ever used it. Move the function back again and remove
the header file.
I removed the superfluous uses of inline/INLINE but this is otherwise
a non-functional change.
Refs: https://github.com/libuv/libuv/issues/4819