authorgravatar for quae@daurnimator.comdaurnimator <quae@daurnimator.com> 2020-11-10 10:29:02+11:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-11-09 16:29:22-07:00
log904c513a1e6fee98f4c431fe8213f7f32e18be6a
treece2299af88c202f302d0069ded53733e87317fd7
parent0e2eb6eb651112e27ae996cfdb67a878ddb61f81

Fix json parser close tracking (#6865)

* std: fix json parsing with unmatched closing tokens * std: fix swapped json parsing errors

1 files changed, 26 insertions(+), 5 deletions(-)

lib/std/json.zig+26-5
...@@ -375,7 +375,7 @@ pub const StreamingParser = struct {...@@ -375,7 +375,7 @@ pub const StreamingParser = struct {
375 '}' => {375 '}' => {
376 // unlikely376 // unlikely
377 if (p.stack & 1 != object_bit) {377 if (p.stack & 1 != object_bit) {
378 return error.UnexpectedClosingBracket;378 return error.UnexpectedClosingBrace;
379 }379 }
380 if (p.stack_used == 0) {380 if (p.stack_used == 0) {
381 return error.TooManyClosingItems;381 return error.TooManyClosingItems;
...@@ -401,7 +401,7 @@ pub const StreamingParser = struct {...@@ -401,7 +401,7 @@ pub const StreamingParser = struct {
401 },401 },
402 ']' => {402 ']' => {
403 if (p.stack & 1 != array_bit) {403 if (p.stack & 1 != array_bit) {
404 return error.UnexpectedClosingBrace;404 return error.UnexpectedClosingBracket;
405 }405 }
406 if (p.stack_used == 0) {406 if (p.stack_used == 0) {
407 return error.TooManyClosingItems;407 return error.TooManyClosingItems;
...@@ -571,8 +571,11 @@ pub const StreamingParser = struct {...@@ -571,8 +571,11 @@ pub const StreamingParser = struct {
571 p.state = .ValueBeginNoClosing;571 p.state = .ValueBeginNoClosing;
572 },572 },
573 ']' => {573 ']' => {
574 if (p.stack & 1 != array_bit) {
575 return error.UnexpectedClosingBracket;
576 }
574 if (p.stack_used == 0) {577 if (p.stack_used == 0) {
575 return error.UnbalancedBrackets;578 return error.TooManyClosingItems;
576 }579 }
577580
578 p.state = .ValueEnd;581 p.state = .ValueEnd;
...@@ -589,8 +592,12 @@ pub const StreamingParser = struct {...@@ -589,8 +592,12 @@ pub const StreamingParser = struct {
589 token.* = Token.ArrayEnd;592 token.* = Token.ArrayEnd;
590 },593 },
591 '}' => {594 '}' => {
595 // unlikely
596 if (p.stack & 1 != object_bit) {
597 return error.UnexpectedClosingBrace;
598 }
592 if (p.stack_used == 0) {599 if (p.stack_used == 0) {
593 return error.UnbalancedBraces;600 return error.TooManyClosingItems;
594 }601 }
595602
596 p.state = .ValueEnd;603 p.state = .ValueEnd;
...@@ -1189,6 +1196,15 @@ test "json.token" {...@@ -1189,6 +1196,15 @@ test "json.token" {
1189 testing.expect((try p.next()) == null);1196 testing.expect((try p.next()) == null);
1190}1197}
11911198
1199test "json.token mismatched close" {
1200 var p = TokenStream.init("[102, 111, 111 }");
1201 checkNext(&p, .ArrayBegin);
1202 checkNext(&p, .Number);
1203 checkNext(&p, .Number);
1204 checkNext(&p, .Number);
1205 testing.expectError(error.UnexpectedClosingBrace, p.next());
1206}
1207
1192/// Validate a JSON string. This does not limit number precision so a decoder may not necessarily1208/// Validate a JSON string. This does not limit number precision so a decoder may not necessarily
1193/// be able to decode the string even if this returns true.1209/// be able to decode the string even if this returns true.
1194pub fn validate(s: []const u8) bool {1210pub fn validate(s: []const u8) bool {
...@@ -1207,7 +1223,12 @@ pub fn validate(s: []const u8) bool {...@@ -1207,7 +1223,12 @@ pub fn validate(s: []const u8) bool {
1207}1223}
12081224
1209test "json.validate" {1225test "json.validate" {
1210 testing.expect(validate("{}"));1226 testing.expectEqual(true, validate("{}"));
1227 testing.expectEqual(true, validate("[]"));
1228 testing.expectEqual(true, validate("[{[[[[{}]]]]}]"));
1229 testing.expectEqual(false, validate("{]"));
1230 testing.expectEqual(false, validate("[}"));
1231 testing.expectEqual(false, validate("{{{{[]}}}]"));
1211}1232}
12121233
1213const Allocator = std.mem.Allocator;1234const Allocator = std.mem.Allocator;