aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2017-06-01 17:57:13 -0500
committerGitHub <noreply@github.com>2017-06-01 17:57:13 -0500
commit00c1763e0b89337f980d18888bb1935f250afd7b (patch)
treefcfde60a5d645769d536f9b7c0726560ed225a14
parent36431af975092578648225c60a8494cb0d5f6844 (diff)
parent2dfc9fedd30bf3d40c4c3e97adc06fe3aad34361 (diff)
downloadmilf-rs-00c1763e0b89337f980d18888bb1935f250afd7b.tar.gz
milf-rs-00c1763e0b89337f980d18888bb1935f250afd7b.zip
Merge pull request #187 from alanhdu/master
More fuzzing fixes
-rw-r--r--src/datetime.rs44
-rw-r--r--src/ser.rs10
-rw-r--r--tests/parser.rs2
-rw-r--r--tests/valid.rs6
-rw-r--r--tests/valid/datetime-truncate.json6
-rw-r--r--tests/valid/datetime-truncate.toml1
-rw-r--r--tests/valid/key-quote-newline.json3
-rw-r--r--tests/valid/key-quote-newline.toml1
8 files changed, 45 insertions, 28 deletions
diff --git a/src/datetime.rs b/src/datetime.rs
index f39d9fa..83b5c0b 100644
--- a/src/datetime.rs
+++ b/src/datetime.rs
@@ -55,7 +55,7 @@ struct Time {
hour: u8,
minute: u8,
second: u8,
- secfract: f64,
+ nanosecond: u32,
}
#[derive(PartialEq, Clone)]
@@ -97,9 +97,9 @@ impl fmt::Display for Date {
impl fmt::Display for Time {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:02}:{:02}:{:02}", self.hour, self.minute, self.second)?;
- if self.secfract != 0.0 {
- let s = format!("{}", self.secfract);
- write!(f, "{}", s.trim_left_matches("0"))?;
+ if self.nanosecond != 0 {
+ let s = format!("{:09}", self.nanosecond);
+ write!(f, ".{}", s.trim_right_matches('0'))?;
}
Ok(())
}
@@ -199,38 +199,37 @@ impl FromStr for Datetime {
let s1 = 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();
- let mut first = true;
let whole = chars.as_str();
+
let mut end = whole.len();
- for (i, c) in whole.char_indices() {
- match c {
- '0' ... '9' => {}
+ for (i, byte) in whole.bytes().enumerate() {
+ match byte {
+ 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;
- break
+ break;
}
}
- first = false;
}
- if first {
+ if end == 0 {
return Err(DatetimeParseError { _private: () })
}
chars = whole[end..].chars();
- match format!("0.{}", &whole[..end]).parse() {
- Ok(f) => f,
- Err(_) => return Err(DatetimeParseError { _private: () }),
- }
- } else {
- 0.0
- };
+ }
let time = Time {
hour: h1 * 10 + h2,
minute: m1 * 10 + m2,
second: s1 * 10 + s2,
- secfract: secfract,
+ nanosecond: nanosecond,
};
if time.hour > 24 {
@@ -239,7 +238,10 @@ impl FromStr for Datetime {
if time.minute > 59 {
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: () })
}
diff --git a/src/ser.rs b/src/ser.rs
index 8f6b366..77db867 100644
--- a/src/ser.rs
+++ b/src/ser.rs
@@ -107,7 +107,8 @@ pub enum Error {
/// attempted where the key of a map was not a string.
KeyNotString,
- /// Keys in maps are not allowed to have newlines.
+ /// An error that we never omit but keep for backwards compatibility
+ #[doc(hidden)]
KeyNewline,
/// 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, .. } => {
key.truncate(0);
*key = input.serialize(StringExtractor)?;
- if key.contains('\n') {
- return Err(Error::KeyNewline)
- }
}
}
Ok(())
@@ -1047,13 +1045,13 @@ impl fmt::Display for Error {
match *self {
Error::UnsupportedType => "unsupported Rust type".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::ValueAfterTable => "values must be emitted before tables".fmt(f),
Error::DateInvalid => "a serialized date was invalid".fmt(f),
Error::NumberInvalid => "a serialized number was invalid".fmt(f),
Error::UnsupportedNone => "unsupported None value".fmt(f),
Error::Custom(ref s) => s.fmt(f),
+ Error::KeyNewline => unreachable!(),
Error::__Nonexhaustive => panic!(),
}
}
@@ -1064,13 +1062,13 @@ impl error::Error for Error {
match *self {
Error::UnsupportedType => "unsupported Rust type",
Error::KeyNotString => "map key was not a string",
- Error::KeyNewline => "map keys cannot contain newlines",
Error::ArrayMixedType => "arrays cannot have mixed types",
Error::ValueAfterTable => "values must be emitted before tables",
Error::DateInvalid => "a serialized date was invalid",
Error::NumberInvalid => "a serialized number was invalid",
Error::UnsupportedNone => "unsupported None value",
Error::Custom(_) => "custom error",
+ Error::KeyNewline => unreachable!(),
Error::__Nonexhaustive => panic!(),
}
}
diff --git a/tests/parser.rs b/tests/parser.rs
index 2db2cfb..2282416 100644
--- a/tests/parser.rs
+++ b/tests/parser.rs
@@ -463,7 +463,7 @@ fn datetimes() {
t!("2016-09-09T09:09:09Z");
t!("2016-09-09T09:09:09.1Z");
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-9-09T09:09:09Z", "failed to parse date");
bad!("foo = 2016-09-09T09:09:09+2:00", "failed to parse date");
diff --git a/tests/valid.rs b/tests/valid.rs
index 676fc67..e7577ad 100644
--- a/tests/valid.rs
+++ b/tests/valid.rs
@@ -190,6 +190,12 @@ test!(example_bom,
include_str!("valid/example-bom.toml"),
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,
include_str!("valid/table-array-nest-no-keys.toml"),
include_str!("valid/table-array-nest-no-keys.json"));
diff --git a/tests/valid/datetime-truncate.json b/tests/valid/datetime-truncate.json
new file mode 100644
index 0000000..8c512e1
--- /dev/null
+++ b/tests/valid/datetime-truncate.json
@@ -0,0 +1,6 @@
+{
+ "bestdayever": {
+ "type": "datetime",
+ "value": "1987-07-05T17:45:00.123456789Z"
+ }
+}
diff --git a/tests/valid/datetime-truncate.toml b/tests/valid/datetime-truncate.toml
new file mode 100644
index 0000000..05de841
--- /dev/null
+++ b/tests/valid/datetime-truncate.toml
@@ -0,0 +1 @@
+bestdayever = 1987-07-05T17:45:00.123456789012345Z
diff --git a/tests/valid/key-quote-newline.json b/tests/valid/key-quote-newline.json
new file mode 100644
index 0000000..12473e4
--- /dev/null
+++ b/tests/valid/key-quote-newline.json
@@ -0,0 +1,3 @@
+{
+ "\n": {"type": "integer", "value": "1"}
+}
diff --git a/tests/valid/key-quote-newline.toml b/tests/valid/key-quote-newline.toml
new file mode 100644
index 0000000..a2639bf
--- /dev/null
+++ b/tests/valid/key-quote-newline.toml
@@ -0,0 +1 @@
+"\n" = 1