aboutsummaryrefslogtreecommitdiff
path: root/src/de/impls.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/de/impls.rs')
-rw-r--r--src/de/impls.rs21
1 files changed, 20 insertions, 1 deletions
diff --git a/src/de/impls.rs b/src/de/impls.rs
index 409f6cb..59d90d2 100644
--- a/src/de/impls.rs
+++ b/src/de/impls.rs
@@ -2046,6 +2046,17 @@ impl<'de> Deserialize<'de> for SystemTime {
}
}
+ fn check_overflow<E>(secs: u64, nanos: u32) -> Result<(), E>
+ where
+ E: Error,
+ {
+ static NANOS_PER_SEC: u32 = 1_000_000_000;
+ match secs.checked_add((nanos / NANOS_PER_SEC) as u64) {
+ Some(_) => Ok(()),
+ None => Err(E::custom("overflow deserializing SystemTime epoch offset")),
+ }
+ }
+
struct DurationVisitor;
impl<'de> Visitor<'de> for DurationVisitor {
@@ -2071,6 +2082,7 @@ impl<'de> Deserialize<'de> for SystemTime {
return Err(Error::invalid_length(1, &self));
}
};
+ try!(check_overflow(secs, nanos));
Ok(Duration::new(secs, nanos))
}
@@ -2108,13 +2120,20 @@ impl<'de> Deserialize<'de> for SystemTime {
Some(nanos) => nanos,
None => return Err(<A::Error as Error>::missing_field("nanos_since_epoch")),
};
+ try!(check_overflow(secs, nanos));
Ok(Duration::new(secs, nanos))
}
}
const FIELDS: &'static [&'static str] = &["secs_since_epoch", "nanos_since_epoch"];
let duration = try!(deserializer.deserialize_struct("SystemTime", FIELDS, DurationVisitor));
- Ok(UNIX_EPOCH + duration)
+ #[cfg(systemtime_checked_add)]
+ let ret = UNIX_EPOCH
+ .checked_add(duration)
+ .ok_or_else(|| D::Error::custom("overflow deserializing SystemTime"));
+ #[cfg(not(systemtime_checked_add))]
+ let ret = Ok(UNIX_EPOCH + duration);
+ ret
}
}