Skip to content

fix: correct underflow in random_updated_at#4363

Open
metalurgical wants to merge 4 commits intocowprotocol:mainfrom
metalurgical:fix/random-updated-at-underflow
Open

fix: correct underflow in random_updated_at#4363
metalurgical wants to merge 4 commits intocowprotocol:mainfrom
metalurgical:fix/random-updated-at-underflow

Conversation

@metalurgical
Copy link
Copy Markdown

@metalurgical metalurgical commented Apr 26, 2026

Description

Fix unchecked subtraction on Instant. Since Duration is not bounded by Instant, large inputs can cause underflow. Clamp to a valid past timestamp on underflow, or now if that could fail.

Changes

  • Replace unchecked with checked_sub
  • Clamp to a valid past timestamp on underflow or now.
  • Add test for large max_age to ensure correct clamping.
  • Add range test for normal behaviour.

How to test

cargo nextest run -p price-estimation random_updated_at_underflow_check
cargo nextest run -p price-estimation random_updated_at_range

Fix unchecked subtraction on `Instant`. Since `Duration` is not bounded by `Instant`, large inputs can cause underflow. Clamp to a valid past timestamp on underflow.
@metalurgical metalurgical requested a review from a team as a code owner April 26, 2026 11:53
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the random_updated_at function to use floating-point multiplication for age calculation and introduces checked_sub to prevent underflow panics when the calculated age exceeds the current time. A unit test was also added to verify this behavior. Feedback was provided regarding the fallback logic, which still contains an unchecked subtraction that could potentially panic if the system uptime is less than one second.

Comment thread crates/price-estimation/src/native_price_cache.rs Outdated
@metalurgical metalurgical force-pushed the fix/random-updated-at-underflow branch from 4c187fa to b66e558 Compare April 26, 2026 14:53
Copy link
Copy Markdown
Contributor

@jmg-duarte jmg-duarte left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

after the saturaring_* changes, please test the edges of the rng (50% and 90%) explicitly too

Comment on lines +202 to +205
let age = max_age
.checked_mul(percent_expired)
.map(|age| age / 100)
.unwrap_or(Duration::MAX);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use saturating_mul instead

Comment on lines +207 to +209
now.checked_sub(age)
.or_else(|| now.checked_sub(Duration::from_secs(1)))
.unwrap_or(now)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use saturating_sub instead

fn random_updated_at_underflow_check() {
let now = Instant::now();
let max_age = Duration::MAX;
let mut rng = rand::rng();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seed the rng for determinism

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants