Skip to content

Commit cfb29f8

Browse files
fix!: fixed invalid json passing as valid json (#32)
1 parent b6bbbd1 commit cfb29f8

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

src/json.nr

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::get_literal::JSONLiteral;
1010
use crate::json_entry::{JSONContextStackEntry, JSONEntry, JSONEntryPacked};
1111
use crate::json_tables::{
1212
JSON_CAPTURE_TABLE, PROCESS_RAW_TRANSCRIPT_TABLE, TOKEN_FLAGS_TABLE,
13-
TOKEN_IS_ARRAY_OBJECT_OR_VALUE, TOKEN_VALIDATION_TABLE,
13+
TOKEN_IS_ARRAY_OBJECT_OR_VALUE, TOKEN_IS_STRING, TOKEN_VALIDATION_TABLE,
1414
};
1515
use crate::token_flags::TokenFlags;
1616
use crate::transcript_entry::{
@@ -127,7 +127,7 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
127127

128128
let next_is_key = (next.token == KEY_SEPARATOR_TOKEN) as Field;
129129

130-
let valid_token = TOKEN_IS_ARRAY_OBJECT_OR_VALUE[current.token];
130+
let valid_token = TOKEN_IS_STRING[current.token];
131131
assert(
132132
(valid_token * next_is_key) + (1 - next_is_key) == 1,
133133
"Cannot find key/value straddling KEY_DELIMITER_TOKEN",
@@ -429,6 +429,13 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
429429
scan_mode = scan_token;
430430
}
431431

432+
// if we end in a scan mode where we're searching for a number, string or a literal (true/false/null), we have an incomplete token and this is invalid JSON
433+
// NOTE: if we upgrade this parser to be able to process single-value JSON (e,g, "999" or ""hello" : "world"" this logic needs to be upgraded)
434+
assert(
435+
scan_mode == GRAMMAR_SCAN as Field,
436+
"build_transcript: incomplete token (number, string or literal)",
437+
);
438+
432439
// ensure an error isn't hiding in the last scanned token
433440
scan_mode.assert_max_bit_size::<2>();
434441
raw_transcript
@@ -936,3 +943,26 @@ fn test_json_empty_array_passes() {
936943
let _: JSON<26, 10, 20, 20, 2> = JSON::parse_json_from_string(text);
937944
}
938945

946+
#[test(should_fail)]
947+
fn test_finishing_with_string_scan_fails() {
948+
let json_string = "{ } \"}";
949+
let _: JSON<26, 10, 20, 20, 2> = JSON::parse_json_from_string(json_string);
950+
}
951+
952+
#[test(should_fail)]
953+
fn test_finishing_with_literal_scan_fails() {
954+
let json_string = "{ } fa";
955+
let _: JSON<26, 10, 20, 20, 2> = JSON::parse_json_from_string(json_string);
956+
}
957+
958+
#[test(should_fail)]
959+
fn test_finishing_with_numeric_scan_fails() {
960+
let json_string = "{ } 123";
961+
let _: JSON<26, 10, 20, 20, 2> = JSON::parse_json_from_string(json_string);
962+
}
963+
964+
#[test(should_fail)]
965+
fn key_is_not_a_key() {
966+
let json_string = "{1\n:0}";
967+
let _: JSON<26, 10, 20, 20, 2> = JSON::parse_json_from_string(json_string);
968+
}

src/json_tables.nr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::enums::Token::NUM_TOKENS_MUL_2;
22

33
global TOKEN_ENDS_OBJECT_OR_ARRAY: [Field; 11] = [0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0];
4+
global TOKEN_IS_STRING: [Field; 11] = [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0];
45
global TOKEN_IS_ARRAY_OBJECT_OR_VALUE: [Field; 11] = [0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0];
56
global TOKEN_FLAGS_TABLE: [Field; NUM_TOKENS_MUL_2] = [
67
0x01,

0 commit comments

Comments
 (0)