dtolnay / request-for-implementation

Crates that don't exist, but should
610 stars 6 forks source link

Types for checked arithmetic on instants and durations #27

Closed dtolnay closed 5 years ago

dtolnay commented 5 years ago

The std::time::Instant and std::time::Duration types are quite tricky to use correctly for arithmetic because their arithmetic operators panic on overflow and their non-panicking methods are unergonomic.

Consider a use case drawn from TURN_Hammer in which we receive untrusted input representing seconds and subsec-nanoseconds elapsed since some prearranged base instant, and we need to compute a value rtt4 which is the duration elapsed since the untrusted moment. Naively the code would be:

let now = Instant::now();
if now > deadline {
    break;
}

let s: u64 = /* untrusted */;
let ns: u32 = /* untrusted */;

let since_base = Duration::new(s, ns);
let remote_instant = base_instant + since_base;
let rtt4 = now - remote_instant;

The problem is all three of the last three lines can panic in the face of untrusted input.

The checked version of the same logic is harder to write and much less readable.

let s = Duration::from_secs(/* untrusted */);
let ns = Duration::from_nanos(/* untrusted */);

let since_base = s.checked_add(ns)?;
let remote_instant = base_instant.checked_add(since_base)?;
let rtt4 = now.checked_duration_since(remote_instant)?;

I would like a library that provides wrapper types for safely performing panic-free checked arithmetic on instants and durations such that the naive readable code is also secure:

use easytime::{Duration, Instant};

let s: u64 = /* untrusted */;
let ns: u32 = /* untrusted */;

let since_base = Duration::new(s, ns);
let rtt4 = now - (base_instant + since_base);

// some method to go from easytime::Duration to std::time::Duration:
let rtt4 = rtt4.unwrap_or(...);
taiki-e commented 5 years ago

I ended up the basic implementation of this : https://github.com/taiki-e/easytime

(I would like to confirm that there is not much difference from what this issue aims.)

dtolnay commented 5 years ago

Nice, looks good to me. I will close out this issue once your crate is published.

I filed https://github.com/taiki-e/easytime/issues/1 to consider adding example code.

taiki-e commented 5 years ago

Thanks, done: https://crates.io/crates/easytime

dtolnay commented 5 years ago

Excellent. I added a link to your crate from the readme.