Skip to content

Commit

Permalink
[#64] Captured invalid timestamp, preventing chrono panicking
Browse files Browse the repository at this point in the history
  • Loading branch information
zonyitoo committed Jun 27, 2018
1 parent 60745f1 commit c72166d
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 3 deletions.
11 changes: 10 additions & 1 deletion src/decoder/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::{error, fmt, io, string};
use std::fmt::Display;
use std::{error, fmt, io, string};

use serde::de::{self, Expected, Unexpected};

Expand Down Expand Up @@ -28,6 +28,11 @@ pub enum DecoderError {
UnknownVariant(String),
// Invalid value
InvalidValue(String),
// Invalid timestamp
InvalidTimestamp(i64),
// Ambiguous timestamp
AmbiguousTimestamp(i64),

Unknown(String),
}

Expand Down Expand Up @@ -62,6 +67,8 @@ impl fmt::Display for DecoderError {
DecoderError::UnknownVariant(ref var) => write!(fmt, "unknown variant `{}`", var),
DecoderError::InvalidValue(ref desc) => desc.fmt(fmt),
DecoderError::Unknown(ref inner) => inner.fmt(fmt),
DecoderError::InvalidTimestamp(ref i) => write!(fmt, "no such local time {}", i),
DecoderError::AmbiguousTimestamp(ref i) => write!(fmt, "ambiguous local time {}", i),
}
}
}
Expand All @@ -83,6 +90,8 @@ impl error::Error for DecoderError {
DecoderError::UnknownVariant(_) => "unknown variant",
DecoderError::InvalidValue(ref desc) => desc,
DecoderError::Unknown(ref inner) => inner,
DecoderError::InvalidTimestamp(..) => "no such local time",
DecoderError::AmbiguousTimestamp(..) => "ambiguous local time",
}
}
fn cause(&self) -> Option<&error::Error> {
Expand Down
9 changes: 7 additions & 2 deletions src/decoder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ pub use self::serde::Decoder;
use std::io::Read;

use byteorder::{LittleEndian, ReadBytesExt};
use chrono::offset::{LocalResult, TimeZone};
use chrono::Utc;
use chrono::offset::TimeZone;

use bson::{Array, Bson, Document};
use oid;
Expand Down Expand Up @@ -199,7 +199,12 @@ fn decode_bson<R: Read + ?Sized>(reader: &mut R, tag: u8, utf8_lossy: bool) -> D
Some(TimeStamp) => read_i64(reader).map(Bson::TimeStamp),
Some(UtcDatetime) => {
let time = read_i64(reader)?;
Ok(Bson::UtcDatetime(Utc.timestamp(time / 1000, (time % 1000) as u32 * 1000000)))

match Utc.timestamp_opt(time / 1000, (time % 1000) as u32 * 1000000) {
LocalResult::None => Err(DecoderError::InvalidTimestamp(time)),
LocalResult::Ambiguous(..) => Err(DecoderError::AmbiguousTimestamp(time)),
LocalResult::Single(t) => Ok(Bson::UtcDatetime(t)),
}
}
Some(Symbol) => read_string(reader, utf8_lossy).map(Bson::Symbol),
Some(Undefined) | Some(DbPointer) | Some(MaxKey) | Some(MinKey) | None => {
Expand Down

0 comments on commit c72166d

Please sign in to comment.