-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Fix sigaddset/sigdelset bit-fiddling math #23502
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
I feel like we should |
Yeah, this is programmer error, and users are very likely to just be passing in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems fine; the suggested cleanup above is optional since it's no worse than what was there already.
The code was using u32 and usize interchangably, which doesn't work on 64-bit systems. This: `pub const sigset_t = [1024 / 32]u32;` is not consistent with this: `const shift = @as(u5, @intcast(s & (usize_bits - 1)));` However, normal signal numbers are less than 31, so the bad math doesn't matter much. Also, despite support for 1024 signals in the set, only setting signals between 1 and NSIG (which is mostly 65, but sometimes 128) is defined. The existing tests only exercised signal numbers in the first 31 bits so they didn't trip over this: The C library `sigaddset` will return `EINVAL` if given an out of bounds signal number. I made the Zig code just silently ignore any out of bounds signal numbers. Moved all the `sigset` related declarations next to each in the source, too. The `filled_sigset` seems non-standard to me. I think it is meant to be used like `empty_sigset`, but it only contains 31 set signals, which seems wrong (should be 64 or 128, aka `NSIG`). It's also unused. The oddly named but similar `all_mask` is used (by posix.zig) but sets all 1024 bits (which I understood to be undefined behavior but seems to work just fine). For comparison the musl `sigfillset` fills in 65 bits or 128 bits.
The code was using
u32
andusize
interchangably, which doesn't work on 64-bit systems. This:pub const sigset_t = [1024 / 32]u32;
is not consistent with this:const shift = @as(u5, @intCast(s & (usize_bits - 1)));
However, normal signal numbers are less than 31, so the bad math doesn't matter much. Also, despite support for 1024 signals in the set, only setting signals between 1 and
NSIG
(which is mostly 65, but sometimes 128) is defined. The existing tests only exercised signal numbers in the first 31 bits so they didn't trigger the overflow.The C library
sigaddset
will returnEINVAL
if given an out of bounds signal number. I made the Zig code just silently ignore any out of bounds signal numbers.I moved all the
sigset
related declarations to be adjacent in the source, too.The
filled_sigset
seems non-standard to me. I think it is meant to be used likeempty_sigset
, but it only contains 31 set signals, which seems wrong (should be 64 or 128, akaNSIG
). It's also unused. The oddly named but similarall_mask
is used (byposix.zig
) but sets all 1024 bits (which I understood to be undefined behavior but seems to work just fine). For comparison the muslsigfillset
only fills in 64 bits (or 128 bits).