Skip to content

Commit

Permalink
Fix float -> u128 conversion bug
Browse files Browse the repository at this point in the history
Converting floats to u128 failed because in the comparison
"src > u128::MAX as f32" we invoked UB due to the
u128::MAX as f32 conversion.
  • Loading branch information
est31 committed May 7, 2017
1 parent f5ccf5f commit c238aed
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 1 deletion.
35 changes: 34 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,37 @@ macro_rules! from_float {
}
}

/// From a float `$src` to an integer `$dst`, where $dst is large enough to contain
/// all values of `$src`. We can't ever overflow here
macro_rules! from_float_dst {
($($src:ident => $($dst:ident),+);+;) => {
$(
$(
impl From<$src> for $dst {
type Output = Result<$dst, Error>;

#[inline]
#[allow(unused_comparisons)]
fn cast(src: $src) -> Self::Output {
use core::{$dst, $src};

Err(if src != src {
Error::NaN
} else if src == $src::INFINITY ||
src == $src::NEG_INFINITY {
Error::Infinite
} else if ($dst::MIN == 0) && src < 0.0 {
Error::Underflow
} else {
return Ok(src as $dst);
})
}
}
)+
)+
}
}

// PLAY TETRIS! ;-)

#[cfg(target_pointer_width = "32")]
Expand Down Expand Up @@ -463,9 +494,11 @@ mod _x128 {

// Float
from_float! {
f32 => i128, u128;
f64 => i128, u128;
}
from_float_dst! {
f32 => i128, u128;
}
}

// The missing piece
Expand Down
6 changes: 6 additions & 0 deletions src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,9 @@ from_float! {
f32 => i128, u128;
f64 => i128, u128;
}*/

#[test]
fn test_fl_conversion() {
use u128;
assert_eq!(u128(42.0f32), Ok(42));
}

0 comments on commit c238aed

Please sign in to comment.