Skip to content
This repository was archived by the owner on Jul 9, 2023. It is now read-only.
This repository was archived by the owner on Jul 9, 2023. It is now read-only.

Types for checked arithmetic on instants and durations #27

@dtolnay

Description

@dtolnay

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.

  • let since_base panics if s + ns / 1e9 > u64::max_value();
  • let remote_instant panics on overflow;
  • let rtt4 panics if remote_instant > now.

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(...);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions