Merge pull request #4429 from RalfJung/futex-val-too-big

linux futex: fix for val > i32::MAX
This commit is contained in:
Ralf Jung 2025-06-30 06:48:18 +00:00 committed by GitHub
commit 8bb5f8cae4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 9 additions and 3 deletions

View file

@ -15,12 +15,13 @@ pub fn futex<'tcx>(
) -> InterpResult<'tcx> {
let [addr, op, val] = check_min_vararg_count("`syscall(SYS_futex, ...)`", varargs)?;
// See <https://man7.org/linux/man-pages/man2/futex.2.html> for docs.
// The first three arguments (after the syscall number itself) are the same to all futex operations:
// (int *addr, int op, int val).
// (uint32_t *addr, int op, uint32_t val).
// We checked above that these definitely exist.
let addr = ecx.read_pointer(addr)?;
let op = ecx.read_scalar(op)?.to_i32()?;
let val = ecx.read_scalar(val)?.to_i32()?;
let val = ecx.read_scalar(val)?.to_u32()?;
// This is a vararg function so we have to bring our own type for this pointer.
let addr = ecx.ptr_to_mplace(addr, ecx.machine.layouts.i32);
@ -138,7 +139,7 @@ pub fn futex<'tcx>(
// It's not uncommon for `addr` to be passed as another type than `*mut i32`, such as `*const AtomicI32`.
// We do an acquire read -- it only seems reasonable that if we observe a value here, we
// actually establish an ordering with that value.
let futex_val = ecx.read_scalar_atomic(&addr, AtomicReadOrd::Acquire)?.to_i32()?;
let futex_val = ecx.read_scalar_atomic(&addr, AtomicReadOrd::Acquire)?.to_u32()?;
if val == futex_val {
// The value still matches, so we block the thread and make it wait for FUTEX_WAKE.

View file

@ -33,6 +33,11 @@ fn wake_nobody() {
0,
);
}
// Wake u32::MAX waiters.
unsafe {
assert_eq!(libc::syscall(libc::SYS_futex, addr_of!(futex), libc::FUTEX_WAKE, u32::MAX), 0);
}
}
fn wake_dangling() {