authorgravatar for 35425444+leoconst@users.noreply.github.comLeo Constantinides <35425444+leoconst@users.noreply.github.com> 2023-02-13 13:44:34+00:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-02-13 15:44:34+02:00
log25d6b8c1f1d5dc532c2bb68057d90751895aea68
tree1579a905d7320cd67bf99524ddef525b161518df
parentf62e3b8c0dd232bddb559405b00c1c1c4815f359
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

std: support deserialising JSON strings containing escape seqences into sentinel slice


1 files changed, 17 insertions(+), 7 deletions(-)

lib/std/json.zig+17-7
......@@ -1678,19 +1678,16 @@ fn parseInternal(
16781678 if (ptrInfo.child != u8) return error.UnexpectedToken;
16791679 const source_slice = stringToken.slice(tokens.slice, tokens.i - 1);
16801680 const len = stringToken.decodedLength();
1681 const output = try allocator.alloc(u8, len + @boolToInt(ptrInfo.sentinel != null));
1681 const output = if (ptrInfo.sentinel) |sentinel_ptr|
1682 try allocator.allocSentinel(u8, len, @ptrCast(*const u8, sentinel_ptr).*)
1683 else
1684 try allocator.alloc(u8, len);
16821685 errdefer allocator.free(output);
16831686 switch (stringToken.escapes) {
16841687 .None => mem.copy(u8, output, source_slice),
16851688 .Some => try unescapeValidString(output, source_slice),
16861689 }
16871690
1688 if (ptrInfo.sentinel) |some| {
1689 const char = @ptrCast(*const u8, some).*;
1690 output[len] = char;
1691 return output[0..len :char];
1692 }
1693
16941691 return output;
16951692 },
16961693 else => return error.UnexpectedToken,
......@@ -2684,3 +2681,16 @@ test "encodesTo" {
26842681 try testing.expectEqual(true, encodesTo("😂", "\\ud83d\\ude02"));
26852682 try testing.expectEqual(true, encodesTo("withąunicode😂", "with\\u0105unicode\\ud83d\\ude02"));
26862683}
2684
2685test "issue 14600" {
2686 const json = "\"\\n\"";
2687 var token_stream = std.json.TokenStream.init(json);
2688 const options = ParseOptions{ .allocator = std.testing.allocator };
2689
2690 // Pre-fix, this line would panic:
2691 const result = try std.json.parse([:0]const u8, &token_stream, options);
2692 defer std.json.parseFree([:0]const u8, result, options);
2693
2694 // Double-check that we're getting the right result
2695 try testing.expect(mem.eql(u8, result, "\n"));
2696}