diff --git a/fuzz/fuzz_targets/compare_to_serde.rs b/fuzz/fuzz_targets/compare_to_serde.rs index 452fafb..779c192 100644 --- a/fuzz/fuzz_targets/compare_to_serde.rs +++ b/fuzz/fuzz_targets/compare_to_serde.rs @@ -82,7 +82,20 @@ fn remove_suffix(s: &str) -> &str { } fn errors_equal(jiter_error: &JiterError, serde_error: &SerdeError) -> bool { - remove_suffix(&jiter_error.to_string()) == remove_suffix(&serde_error.to_string()) + let jiter_error_str = jiter_error.to_string(); + let serde_error_str = serde_error.to_string(); + if jiter_error_str.starts_with("invalid escape at") { + // strings like `"\"\\u\\"` give a EOF error for serde and invalid escape for jiter + true + } else if serde_error_str.starts_with("number out of range") { + // ignore this case as serde is stricter so fails on this before jiter does + true + } else if serde_error_str.starts_with("recursion limit exceeded") { + // serde has a different recursion limit to jiter + true + } else { + remove_suffix(&jiter_error_str) == remove_suffix(&serde_error_str) + } } fuzz_target!(|json: String| { @@ -100,8 +113,9 @@ fuzz_target!(|json: String| { if errors_equal(&jiter_error, &serde_error) { return } else { - dbg!(&jiter_error, jiter_error.to_string(), &serde_error, serde_error.to_string()); + dbg!(json, &jiter_error, jiter_error.to_string(), &serde_error, serde_error.to_string()); panic!("errors not not equal"); + // return } } } diff --git a/src/parse.rs b/src/parse.rs index 2d33fda..f2361e5 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -92,18 +92,7 @@ impl<'a> Parser<'a> { } } } else { - json_err!(EofWhileParsingList, self.index) - } - } - - pub fn peak_object_value(&mut self) -> JsonResult { - if let Some(next) = self.eat_whitespace() { - match Peak::new(next) { - Some(p) => Ok(p), - None => json_err!(ExpectedSomeValue, self.index + 1), - } - } else { - json_err!(EofWhileParsingObject, self.index + 1) + json_err!(EofWhileParsingValue, self.index) } } @@ -176,7 +165,7 @@ impl<'a> Parser<'a> { Some(b'"') => self.object_key::(tape).map(Some), Some(b'}') => json_err!(TrailingComma, self.index + 1), Some(_) => json_err!(KeyMustBeAString, self.index + 1), - None => json_err!(EofWhileParsingObject, self.index), + None => json_err!(EofWhileParsingValue, self.index), } } b'}' => { diff --git a/src/python.rs b/src/python.rs index 6bc3698..b95eb17 100644 --- a/src/python.rs +++ b/src/python.rs @@ -82,12 +82,12 @@ impl<'j> PythonParser<'j> { let dict = PyDict::new(py); if let Some(first_key) = self.parser.object_first::(&mut self.tape).map_err(mje)? { let first_key = PyString::new(py, first_key); - let peak = self.parser.peak_object_value().map_err(mje)?; + let peak = self.parser.peak().map_err(mje)?; let first_value = self._check_take_value(py, peak)?; dict.set_item(first_key, first_value)?; while let Some(key) = self.parser.object_step::(&mut self.tape).map_err(mje)? { let key = PyString::new(py, key); - let peak = self.parser.peak_object_value().map_err(mje)?; + let peak = self.parser.peak().map_err(mje)?; let value = self._check_take_value(py, peak)?; dict.set_item(key, value)?; } diff --git a/src/value.rs b/src/value.rs index bffa4be..f33fe66 100644 --- a/src/value.rs +++ b/src/value.rs @@ -134,14 +134,14 @@ pub(crate) fn take_value( let mut object = LazyIndexMap::new(); if let Some(first_key) = parser.object_first::(tape)? { let first_key = first_key.to_string(); - let peak = parser.peak_object_value()?; + let peak = parser.peak()?; check_recursion!(recursion_limit, parser.index, let first_value = take_value(peak, parser, tape, recursion_limit)?; ); object.insert(first_key, first_value); while let Some(key) = parser.object_step::(tape)? { let key = key.to_string(); - let peak = parser.peak_object_value()?; + let peak = parser.peak()?; check_recursion!(recursion_limit, parser.index, let value = take_value(peak, parser, tape, recursion_limit)?; ); diff --git a/tests/main.rs b/tests/main.rs index a12c183..f4afdf4 100644 --- a/tests/main.rs +++ b/tests/main.rs @@ -11,19 +11,12 @@ use jiter::{ NumberInt, Parser, Peak, StringDecoder, StringDecoderRange, }; -enum PeakMode { - Start, - Array, - Object, -} - -fn json_vec(parser: &mut Parser, peak_mode: PeakMode) -> JsonResult> { +fn json_vec(parser: &mut Parser, in_array: bool) -> JsonResult> { let mut v = Vec::new(); let mut tape: Vec = Vec::new(); - let peak = match peak_mode { - PeakMode::Start => parser.peak()?, - PeakMode::Array => parser.peak_array_step()?, - PeakMode::Object => parser.peak_object_value()?, + let peak = match in_array { + true => parser.peak_array_step()?, + false => parser.peak()?, }; let position = parser.current_position().short(); @@ -52,7 +45,7 @@ fn json_vec(parser: &mut Parser, peak_mode: PeakMode) -> JsonResult> v.push(format!("[ @ {position}")); if parser.array_first()?.is_some() { loop { - let el_vec = json_vec(parser, PeakMode::Array)?; + let el_vec = json_vec(parser, true)?; v.extend(el_vec); if !parser.array_step()? { break; @@ -65,11 +58,11 @@ fn json_vec(parser: &mut Parser, peak_mode: PeakMode) -> JsonResult> v.push(format!("{{ @ {position}")); if let Some(key) = parser.object_first::(&mut tape)? { v.push(format!("Key({key:?})")); - let value_vec = json_vec(parser, PeakMode::Object)?; + let value_vec = json_vec(parser, false)?; v.extend(value_vec); while let Some(key) = parser.object_step::(&mut tape)? { v.push(format!("Key({key:?}")); - let value_vec = json_vec(parser, PeakMode::Object)?; + let value_vec = json_vec(parser, false)?; v.extend(value_vec); } } @@ -103,7 +96,7 @@ macro_rules! single_expect_ok_or_error { #[test] fn [< single_element_ok__ $name >]() { let mut parser = Parser::new($json.as_bytes()); - let elements = json_vec(&mut parser, PeakMode::Start).unwrap().join(", "); + let elements = json_vec(&mut parser, false).unwrap().join(", "); assert_eq!(elements, $expected); parser.finish().unwrap(); } @@ -116,7 +109,7 @@ macro_rules! single_expect_ok_or_error { #[test] fn [< single_element_xerror__ $name >]() { let mut parser = Parser::new($json.as_bytes()); - let result = json_vec(&mut parser, PeakMode::Start); + let result = json_vec(&mut parser, false); let first_value = match result { Ok(v) => v, Err(e) => { @@ -206,8 +199,11 @@ single_tests! { object_trailing_comma: err => r#"{"foo": "bar",}"#, "TrailingComma @ 1:15"; array_trailing_comma: err => r#"[1, 2,]"#, "TrailingComma @ 1:7"; array_wrong_char_after_comma: err => r#"[1, 2,;"#, "ExpectedSomeValue @ 1:7"; + array_end_after_comma: err => "[9,", "EofWhileParsingValue @ 1:3"; object_wrong_char: err => r#"{"foo":42;"#, "ExpectedObjectCommaOrEnd @ 1:10"; object_wrong_char_after_comma: err => r#"{"foo":42,;"#, "KeyMustBeAString @ 1:11"; + object_end_after_comma: err => r#"{"x": 9,"#, "EofWhileParsingValue @ 1:8"; + object_end_after_colon: err => r#"{"":"#, "EofWhileParsingValue @ 1:4"; array_bool: ok => "[true, false]", "[ @ 1:0, true @ 1:1, false @ 1:7, ]"; object_string: ok => r#"{"foo": "ba"}"#, "{ @ 1:0, Key(2..5), String(9..11) @ 1:8, }"; object_null: ok => r#"{"foo": null}"#, "{ @ 1:0, Key(2..5), null @ 1:8, }";