Skip to content

Commit

Permalink
Merge pull request #1958 from jonasbb/duration-panic
Browse files Browse the repository at this point in the history
Prevent panic when deserializing malformed Duration
  • Loading branch information
dtolnay committed Jan 23, 2021
2 parents 398fba9 + b276849 commit 44b9567
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 0 deletions.
13 changes: 13 additions & 0 deletions serde/src/de/impls.rs
Expand Up @@ -1849,6 +1849,17 @@ impl<'de> Deserialize<'de> for Duration {
}
}

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 Duration")),
}
}

struct DurationVisitor;

impl<'de> Visitor<'de> for DurationVisitor {
Expand All @@ -1874,6 +1885,7 @@ impl<'de> Deserialize<'de> for Duration {
return Err(Error::invalid_length(1, &self));
}
};
try!(check_overflow(secs, nanos));
Ok(Duration::new(secs, nanos))
}

Expand Down Expand Up @@ -1907,6 +1919,7 @@ impl<'de> Deserialize<'de> for Duration {
Some(nanos) => nanos,
None => return Err(<A::Error as Error>::missing_field("nanos")),
};
try!(check_overflow(secs, nanos));
Ok(Duration::new(secs, nanos))
}
}
Expand Down
21 changes: 21 additions & 0 deletions test_suite/tests/test_de.rs
Expand Up @@ -1452,4 +1452,25 @@ declare_error_tests! {
],
"invalid value: integer `65536`, expected u16",
}
test_duration_overflow_seq<Duration> {
&[
Token::Seq { len: Some(2) },
Token::U64(u64::max_value()),
Token::U32(1_000_000_000),
Token::SeqEnd,
],
"overflow deserializing Duration",
}
test_duration_overflow_struct<Duration> {
&[
Token::Struct { name: "Duration", len: 2 },
Token::Str("secs"),
Token::U64(u64::max_value()),

Token::Str("nanos"),
Token::U32(1_000_000_000),
Token::StructEnd,
],
"overflow deserializing Duration",
}
}

0 comments on commit 44b9567

Please sign in to comment.