Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/unix/linux_like/android/b32/arm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ s! {

pub struct __c_anonymous_uc_sigmask_with_padding {
pub uc_sigmask: crate::sigset_t,
/* Android has a wrong (smaller) sigset_t on x86. */
/* Android has a wrong (smaller) sigset_t on ARM. */
__padding_rt_sigset: Padding<u32>,
}

Expand Down
26 changes: 25 additions & 1 deletion src/unix/linux_like/android/b64/aarch64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ s! {
pub uc_flags: c_ulong,
pub uc_link: *mut ucontext_t,
pub uc_stack: crate::stack_t,
pub uc_sigmask: crate::sigset_t,
pub uc_sigmask__c_anonymous_union: __c_anonymous_uc_sigmask,
/* The kernel adds extra padding after uc_sigmask to match
* glibc sigset_t on ARM64. */
__padding: Padding<[c_char; 128 - size_of::<crate::sigset_t>()]>,

@teor2345 teor2345 Jun 25, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this subtracting sigset_t (32 bit?), but the comment refers to ARM64?

This calculation seems weird for either 32-bit or 64-bit, and might need further comments:

  • the union is the size of sigset64_t (assuming it's bigger) but we subtract sigset_t (the 32-bit size) from the padding

View changes since the review

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pub uc_mcontext: mcontext_t,
}

Expand All @@ -85,12 +88,33 @@ s! {
}

s_no_extra_traits! {
pub union __c_anonymous_uc_sigmask {
uc_sigmask: crate::sigset_t,
uc_sigmask64: crate::sigset64_t,
}

#[repr(align(16))]
pub struct max_align_t {
priv_: [f32; 8],
}
}

cfg_if! {
if #[cfg(feature = "extra_traits")] {
impl PartialEq for __c_anonymous_uc_sigmask {
fn eq(&self, other: &__c_anonymous_uc_sigmask) -> bool {
unsafe { self.uc_sigmask == other.uc_sigmask }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this sound and correct if the 64-bit sigmask was initialised in the union?

  • if the 64-bit sigmask is larger and has no padding, then the equality check misses some bytes
  • if the 32-bit sigmask is larger (unlikely), then we're comparing uninitialised bytes
  • if there's padding, then does it need to be ignored?

}
}
impl Eq for __c_anonymous_uc_sigmask {}
impl hash::Hash for __c_anonymous_uc_sigmask {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
unsafe { self.uc_sigmask.hash(state) }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, not sure we can do this with unions, without some guarantee they are the same size.

@StackOverflowExcept1on StackOverflowExcept1on Jun 25, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code was simply borrowed from the ARM module:

cfg_if! {
if #[cfg(feature = "extra_traits")] {
impl PartialEq for __c_anonymous_uc_sigmask {
fn eq(&self, other: &__c_anonymous_uc_sigmask) -> bool {
unsafe { self.uc_sigmask == other.uc_sigmask }
}
}
impl Eq for __c_anonymous_uc_sigmask {}
impl hash::Hash for __c_anonymous_uc_sigmask {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
unsafe { self.uc_sigmask.hash(state) }
}
}
}
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

x86_64 has same layout:

cfg_if! {
if #[cfg(feature = "extra_traits")] {
impl PartialEq for __c_anonymous_uc_sigmask {
fn eq(&self, other: &__c_anonymous_uc_sigmask) -> bool {
unsafe { self.uc_sigmask == other.uc_sigmask }
}
}
impl Eq for __c_anonymous_uc_sigmask {}
impl hash::Hash for __c_anonymous_uc_sigmask {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
unsafe { self.uc_sigmask.hash(state) }
}
}
}
}

}
}
}
}

pub const O_DIRECT: c_int = 0x10000;
pub const O_DIRECTORY: c_int = 0x4000;
pub const O_NOFOLLOW: c_int = 0x8000;
Expand Down