Skip to content

Commit

Permalink
Fix panic in DateTime::from_secs_f64 (#3806)
Browse files Browse the repository at this point in the history
## Motivation and Context
- #3805 

## Description
Recover from floating point values extremely close to whole numbers by
incrementing the epoch seconds value.

## Testing
- proptest

## Checklist
<!--- If a checkbox below is not applicable, then please DELETE it
rather than leaving it unchecked -->
- [x] For changes to the smithy-rs codegen or runtime crates, I have
created a changelog entry Markdown file in the `.changelog` directory,
specifying "client," "server," or both in the `applies_to` key.
- [x] For changes to the AWS SDK, generated SDK code, or SDK runtime
crates, I have created a changelog entry Markdown file in the
`.changelog` directory, specifying "aws-sdk-rust" in the `applies_to`
key.

----

_By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice._
  • Loading branch information
rcoh authored Aug 29, 2024
1 parent 35f53b4 commit b38ccb9
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 4 deletions.
9 changes: 9 additions & 0 deletions .changelog/1724779868.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
applies_to: ["client", "server"]
authors: ["rcoh"]
references: ["smithy-rs#3805"]
breaking: false
new_feature: false
bug_fix: true
---
Fix bug in `DateTime::from_secs_f64` where certain floating point values could lead to a panic.
2 changes: 1 addition & 1 deletion aws/rust-runtime/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rust-runtime/aws-smithy-types/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "aws-smithy-types"
version = "1.2.4"
version = "1.2.5"
authors = [
"AWS Rust SDK Team <[email protected]>",
"Russell Cohen <[email protected]>",
Expand Down
31 changes: 29 additions & 2 deletions rust-runtime/aws-smithy-types/src/date_time/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,22 @@ impl DateTime {
/// DateTime::from_fractional_secs(1, 0.5),
/// );
/// ```
pub fn from_fractional_secs(epoch_seconds: i64, fraction: f64) -> Self {
let subsecond_nanos = (fraction * 1_000_000_000_f64) as u32;
pub fn from_fractional_secs(mut epoch_seconds: i64, fraction: f64) -> Self {
// Because of floating point issues, `fraction` can end up being 1.0 leading to
// a full second of subsecond nanos. In that case, rollover the subsecond into the second.
let mut subsecond_nanos = (fraction * 1_000_000_000_f64) as u32;
if subsecond_nanos == 1_000_000_000 {
epoch_seconds += 1;
subsecond_nanos = 0;
}
DateTime::from_secs_and_nanos(epoch_seconds, subsecond_nanos)
}

/// Creates a `DateTime` from a number of seconds and sub-second nanos since the Unix epoch.
///
/// # Panics
/// This function will panic if `subsecond_nanos` is >= 1_000_000_000
///
/// # Example
/// ```
/// # use aws_smithy_types::DateTime;
Expand Down Expand Up @@ -680,6 +689,17 @@ mod test {
assert!(fifth == fifth);
}

/// https://github.com/smithy-lang/smithy-rs/issues/3805
#[test]
fn panic_in_fromsecs_f64() {
assert_eq!(DateTime::from_secs_f64(-1.0), DateTime::from_secs(-1));

assert_eq!(
DateTime::from_secs_f64(-1.95877825437922e-309),
DateTime::from_secs(0)
);
}

const MIN_RFC_3339_MILLIS: i64 = -62135596800000;
const MAX_RFC_3339_MILLIS: i64 = 253402300799999;

Expand All @@ -699,4 +719,11 @@ mod test {
assert_eq!(left.cmp(&right), left_str.cmp(&right_str));
}
}

proptest! {
#[test]
fn from_secs_f64_proptest(secs: f64) {
let _date = DateTime::from_secs_f64(secs);
}
}
}

0 comments on commit b38ccb9

Please sign in to comment.