Merge pull request #1958 from jonasbb/duration-panic

Prevent panic when deserializing malformed Duration
This commit is contained in:
David Tolnay 2021-01-23 00:45:39 -08:00 committed by GitHub
commit 44b9567e21
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 0 deletions

View File

@ -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 {
@ -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))
}
@ -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))
}
}

View File

@ -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",
}
}