mirror of
https://github.com/serde-rs/serde.git
synced 2025-10-02 15:25:38 +00:00
Prevent panic when deserializing malformed Duration
std::time::Duration::new can panic. There is no alternative non-panicing constructor. Check the panic condition beforehand and return an error instead of panicing. Fixes #1933
This commit is contained in:
parent
398fba9b1e
commit
b276849ce1
@ -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;
|
struct DurationVisitor;
|
||||||
|
|
||||||
impl<'de> Visitor<'de> for DurationVisitor {
|
impl<'de> Visitor<'de> for DurationVisitor {
|
||||||
@ -1874,6 +1885,7 @@ impl<'de> Deserialize<'de> for Duration {
|
|||||||
return Err(Error::invalid_length(1, &self));
|
return Err(Error::invalid_length(1, &self));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
try!(check_overflow(secs, nanos));
|
||||||
Ok(Duration::new(secs, nanos))
|
Ok(Duration::new(secs, nanos))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1907,6 +1919,7 @@ impl<'de> Deserialize<'de> for Duration {
|
|||||||
Some(nanos) => nanos,
|
Some(nanos) => nanos,
|
||||||
None => return Err(<A::Error as Error>::missing_field("nanos")),
|
None => return Err(<A::Error as Error>::missing_field("nanos")),
|
||||||
};
|
};
|
||||||
|
try!(check_overflow(secs, nanos));
|
||||||
Ok(Duration::new(secs, nanos))
|
Ok(Duration::new(secs, nanos))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1452,4 +1452,25 @@ declare_error_tests! {
|
|||||||
],
|
],
|
||||||
"invalid value: integer `65536`, expected u16",
|
"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",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user