Merge pull request #187 from alanhdu/master

More fuzzing fixes
This commit is contained in:
Alex Crichton 2017-06-01 17:57:13 -05:00 committed by GitHub
commit 181bff2ee4
8 changed files with 45 additions and 28 deletions

View file

@ -55,7 +55,7 @@ struct Time {
hour: u8, hour: u8,
minute: u8, minute: u8,
second: u8, second: u8,
secfract: f64, nanosecond: u32,
} }
#[derive(PartialEq, Clone)] #[derive(PartialEq, Clone)]
@ -97,9 +97,9 @@ impl fmt::Display for Date {
impl fmt::Display for Time { impl fmt::Display for Time {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:02}:{:02}:{:02}", self.hour, self.minute, self.second)?; write!(f, "{:02}:{:02}:{:02}", self.hour, self.minute, self.second)?;
if self.secfract != 0.0 { if self.nanosecond != 0 {
let s = format!("{}", self.secfract); let s = format!("{:09}", self.nanosecond);
write!(f, "{}", s.trim_left_matches("0"))?; write!(f, ".{}", s.trim_right_matches('0'))?;
} }
Ok(()) Ok(())
} }
@ -199,38 +199,37 @@ impl FromStr for Datetime {
let s1 = digit(&mut chars)?; let s1 = digit(&mut chars)?;
let s2 = digit(&mut chars)?; let s2 = digit(&mut chars)?;
let secfract = if chars.clone().next() == Some('.') { let mut nanosecond = 0;
if chars.clone().next() == Some('.') {
chars.next(); chars.next();
let mut first = true;
let whole = chars.as_str(); let whole = chars.as_str();
let mut end = whole.len(); let mut end = whole.len();
for (i, c) in whole.char_indices() { for (i, byte) in whole.bytes().enumerate() {
match c { match byte {
'0' ... '9' => {} b'0' ... b'9' => {
if i < 9 {
let p = 10_u32.pow(8 - i as u32);
nanosecond += p * (byte - b'0') as u32;
}
}
_ => { _ => {
end = i; end = i;
break break;
} }
} }
first = false;
} }
if first { if end == 0 {
return Err(DatetimeParseError { _private: () }) return Err(DatetimeParseError { _private: () })
} }
chars = whole[end..].chars(); chars = whole[end..].chars();
match format!("0.{}", &whole[..end]).parse() { }
Ok(f) => f,
Err(_) => return Err(DatetimeParseError { _private: () }),
}
} else {
0.0
};
let time = Time { let time = Time {
hour: h1 * 10 + h2, hour: h1 * 10 + h2,
minute: m1 * 10 + m2, minute: m1 * 10 + m2,
second: s1 * 10 + s2, second: s1 * 10 + s2,
secfract: secfract, nanosecond: nanosecond,
}; };
if time.hour > 24 { if time.hour > 24 {
@ -239,7 +238,10 @@ impl FromStr for Datetime {
if time.minute > 59 { if time.minute > 59 {
return Err(DatetimeParseError { _private: () }) return Err(DatetimeParseError { _private: () })
} }
if time.second > 60 { if time.second > 59 {
return Err(DatetimeParseError { _private: () })
}
if time.nanosecond > 999_999_999 {
return Err(DatetimeParseError { _private: () }) return Err(DatetimeParseError { _private: () })
} }

View file

@ -107,7 +107,8 @@ pub enum Error {
/// attempted where the key of a map was not a string. /// attempted where the key of a map was not a string.
KeyNotString, KeyNotString,
/// Keys in maps are not allowed to have newlines. /// An error that we never omit but keep for backwards compatibility
#[doc(hidden)]
KeyNewline, KeyNewline,
/// Arrays in TOML must have a homogenous type, but a heterogeneous array /// Arrays in TOML must have a homogenous type, but a heterogeneous array
@ -624,9 +625,6 @@ impl<'a, 'b> ser::SerializeMap for SerializeTable<'a, 'b> {
SerializeTable::Table { ref mut key, .. } => { SerializeTable::Table { ref mut key, .. } => {
key.truncate(0); key.truncate(0);
*key = input.serialize(StringExtractor)?; *key = input.serialize(StringExtractor)?;
if key.contains('\n') {
return Err(Error::KeyNewline)
}
} }
} }
Ok(()) Ok(())
@ -1047,13 +1045,13 @@ impl fmt::Display for Error {
match *self { match *self {
Error::UnsupportedType => "unsupported Rust type".fmt(f), Error::UnsupportedType => "unsupported Rust type".fmt(f),
Error::KeyNotString => "map key was not a string".fmt(f), Error::KeyNotString => "map key was not a string".fmt(f),
Error::KeyNewline => "map keys cannot contain newlines".fmt(f),
Error::ArrayMixedType => "arrays cannot have mixed types".fmt(f), Error::ArrayMixedType => "arrays cannot have mixed types".fmt(f),
Error::ValueAfterTable => "values must be emitted before tables".fmt(f), Error::ValueAfterTable => "values must be emitted before tables".fmt(f),
Error::DateInvalid => "a serialized date was invalid".fmt(f), Error::DateInvalid => "a serialized date was invalid".fmt(f),
Error::NumberInvalid => "a serialized number was invalid".fmt(f), Error::NumberInvalid => "a serialized number was invalid".fmt(f),
Error::UnsupportedNone => "unsupported None value".fmt(f), Error::UnsupportedNone => "unsupported None value".fmt(f),
Error::Custom(ref s) => s.fmt(f), Error::Custom(ref s) => s.fmt(f),
Error::KeyNewline => unreachable!(),
Error::__Nonexhaustive => panic!(), Error::__Nonexhaustive => panic!(),
} }
} }
@ -1064,13 +1062,13 @@ impl error::Error for Error {
match *self { match *self {
Error::UnsupportedType => "unsupported Rust type", Error::UnsupportedType => "unsupported Rust type",
Error::KeyNotString => "map key was not a string", Error::KeyNotString => "map key was not a string",
Error::KeyNewline => "map keys cannot contain newlines",
Error::ArrayMixedType => "arrays cannot have mixed types", Error::ArrayMixedType => "arrays cannot have mixed types",
Error::ValueAfterTable => "values must be emitted before tables", Error::ValueAfterTable => "values must be emitted before tables",
Error::DateInvalid => "a serialized date was invalid", Error::DateInvalid => "a serialized date was invalid",
Error::NumberInvalid => "a serialized number was invalid", Error::NumberInvalid => "a serialized number was invalid",
Error::UnsupportedNone => "unsupported None value", Error::UnsupportedNone => "unsupported None value",
Error::Custom(_) => "custom error", Error::Custom(_) => "custom error",
Error::KeyNewline => unreachable!(),
Error::__Nonexhaustive => panic!(), Error::__Nonexhaustive => panic!(),
} }
} }

View file

@ -463,7 +463,7 @@ fn datetimes() {
t!("2016-09-09T09:09:09Z"); t!("2016-09-09T09:09:09Z");
t!("2016-09-09T09:09:09.1Z"); t!("2016-09-09T09:09:09.1Z");
t!("2016-09-09T09:09:09.2+10:00"); t!("2016-09-09T09:09:09.2+10:00");
t!("2016-09-09T09:09:09.0123456789-02:00"); t!("2016-09-09T09:09:09.123456789-02:00");
bad!("foo = 2016-09-09T09:09:09.Z", "failed to parse date"); bad!("foo = 2016-09-09T09:09:09.Z", "failed to parse date");
bad!("foo = 2016-9-09T09:09:09Z", "failed to parse date"); bad!("foo = 2016-9-09T09:09:09Z", "failed to parse date");
bad!("foo = 2016-09-09T09:09:09+2:00", "failed to parse date"); bad!("foo = 2016-09-09T09:09:09+2:00", "failed to parse date");

View file

@ -190,6 +190,12 @@ test!(example_bom,
include_str!("valid/example-bom.toml"), include_str!("valid/example-bom.toml"),
include_str!("valid/example.json")); include_str!("valid/example.json"));
test!(datetime_truncate,
include_str!("valid/datetime-truncate.toml"),
include_str!("valid/datetime-truncate.json"));
test!(key_quote_newline,
include_str!("valid/key-quote-newline.toml"),
include_str!("valid/key-quote-newline.json"));
test!(table_array_nest_no_keys, test!(table_array_nest_no_keys,
include_str!("valid/table-array-nest-no-keys.toml"), include_str!("valid/table-array-nest-no-keys.toml"),
include_str!("valid/table-array-nest-no-keys.json")); include_str!("valid/table-array-nest-no-keys.json"));

View file

@ -0,0 +1,6 @@
{
"bestdayever": {
"type": "datetime",
"value": "1987-07-05T17:45:00.123456789Z"
}
}

View file

@ -0,0 +1 @@
bestdayever = 1987-07-05T17:45:00.123456789012345Z

View file

@ -0,0 +1,3 @@
{
"\n": {"type": "integer", "value": "1"}
}

View file

@ -0,0 +1 @@
"\n" = 1