Skip to content

Commit

Permalink
Fix unsoundness in new is_power_of_two fast path
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Feb 1, 2024
1 parent 11f32b7 commit 0350d5d
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 8 deletions.
16 changes: 8 additions & 8 deletions library/core/src/num/uint_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1376,9 +1376,9 @@ macro_rules! uint_impl {
}
// SAFETY: We just checked this is a power of two. and above zero.
let power_used = unsafe { intrinsics::cttz_nonzero(self) as u32 };
if exp > Self::BITS / power_used { return None; } // Division of constants is free
if exp >= Self::BITS / power_used { return None; } // Division of constants is free

// SAFETY: exp <= Self::BITS / power_used
// SAFETY: exp < Self::BITS / power_used
unsafe { Some(intrinsics::unchecked_shl(
1 as Self,
intrinsics::unchecked_mul(power_used, exp) as Self
Expand Down Expand Up @@ -1920,9 +1920,9 @@ macro_rules! uint_impl {
}
// SAFETY: We just checked this is a power of two. and above zero.
let power_used = unsafe { intrinsics::cttz_nonzero(self) as u32 };
if exp > Self::BITS / power_used { return 0; } // Division of constants is free
if exp >= Self::BITS / power_used { return 0; } // Division of constants is free

// SAFETY: exp <= Self::BITS / power_used
// SAFETY: exp < Self::BITS / power_used
unsafe { intrinsics::unchecked_shl(
1 as Self,
intrinsics::unchecked_mul(power_used, exp) as Self
Expand Down Expand Up @@ -2395,9 +2395,9 @@ macro_rules! uint_impl {
}
// SAFETY: We just checked this is a power of two. and above zero.
let power_used = unsafe { intrinsics::cttz_nonzero(self) as u32 };
if exp > Self::BITS / power_used { return (0, true); } // Division of constants is free
if exp >= Self::BITS / power_used { return (0, true); } // Division of constants is free

// SAFETY: exp <= Self::BITS / power_used
// SAFETY: exp < Self::BITS / power_used
unsafe { (intrinsics::unchecked_shl(
1 as Self,
intrinsics::unchecked_mul(power_used, exp) as Self
Expand Down Expand Up @@ -2475,12 +2475,12 @@ macro_rules! uint_impl {
}
// SAFETY: We just checked this is a power of two. and above zero.
let power_used = unsafe { intrinsics::cttz_nonzero(self) as u32 };
if exp > Self::BITS / power_used { // Division of constants is free
if exp >= Self::BITS / power_used { // Division of constants is free
#[allow(arithmetic_overflow)]
return Self::MAX * Self::MAX * 0;
}

// SAFETY: exp <= Self::BITS / power_used
// SAFETY: exp < Self::BITS / power_used
unsafe { intrinsics::unchecked_shl(
1 as Self,
intrinsics::unchecked_mul(power_used, exp) as Self
Expand Down
1 change: 1 addition & 0 deletions library/core/tests/num/int_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ macro_rules! int_module {
assert_eq!(r.saturating_pow(2), 4 as $T);
assert_eq!(r.saturating_pow(3), -8 as $T);
assert_eq!(r.saturating_pow(0), 1 as $T);
assert_eq!(2u64.checked_pow(64), None);
}

#[test]
Expand Down

0 comments on commit 0350d5d

Please sign in to comment.