authorgravatar for john.schmidt.h@gmail.comJohn Schmidt <john.schmidt.h@gmail.com> 2023-02-04 18:44:57+01:00
committergravatar for john.schmidt.h@gmail.comJohn Schmidt <john.schmidt.h@gmail.com> 2023-02-04 20:34:47+01:00
logb42caff2a20eb34073f6a766f55d27288028165a
tree7546598aadbf85261ed91a92cd44b076432952bd
parent73c857415eafc1d0856b6917cada94d8acde41e0

std.json: avoid dangling pointers in ValueTree

Closes https://github.com/ziglang/zig/issues/5229.

2 files changed, 25 insertions(+), 2 deletions(-)

lib/std/json.zig+7-2
......@@ -1163,11 +1163,12 @@ const ArrayList = std.ArrayList;
11631163const StringArrayHashMap = std.StringArrayHashMap;
11641164
11651165pub const ValueTree = struct {
1166 arena: ArenaAllocator,
1166 arena: *ArenaAllocator,
11671167 root: Value,
11681168
11691169 pub fn deinit(self: *ValueTree) void {
11701170 self.arena.deinit();
1171 self.arena.child_allocator.destroy(self.arena);
11711172 }
11721173};
11731174
......@@ -1809,8 +1810,12 @@ pub const Parser = struct {
18091810 pub fn parse(p: *Parser, input: []const u8) !ValueTree {
18101811 var s = TokenStream.init(input);
18111812
1812 var arena = ArenaAllocator.init(p.allocator);
1813 var arena = try p.allocator.create(ArenaAllocator);
1814 errdefer p.allocator.destroy(arena);
1815
1816 arena.* = ArenaAllocator.init(p.allocator);
18131817 errdefer arena.deinit();
1818
18141819 const allocator = arena.allocator();
18151820
18161821 while (try s.next()) |token| {
lib/std/json/test.zig+18
......@@ -2589,6 +2589,24 @@ test "parsing empty string gives appropriate error" {
25892589 try testing.expectError(error.UnexpectedEndOfJson, testParse(arena_allocator.allocator(), ""));
25902590}
25912591
2592test "parse tree should not contain dangling pointers" {
2593 var arena_allocator = std.heap.ArenaAllocator.init(std.testing.allocator);
2594 defer arena_allocator.deinit();
2595
2596 var p = json.Parser.init(arena_allocator.allocator(), false);
2597 defer p.deinit();
2598
2599 var tree = try p.parse("[]");
2600 defer tree.deinit();
2601
2602 // Allocation should succeed
2603 var i: usize = 0;
2604 while (i < 100) : (i += 1) {
2605 try tree.root.Array.append(std.json.Value{ .Integer = 100 });
2606 }
2607 try testing.expectEqual(tree.root.Array.items.len, 100);
2608}
2609
25922610test "integer after float has proper type" {
25932611 var arena_allocator = std.heap.ArenaAllocator.init(std.testing.allocator);
25942612 defer arena_allocator.deinit();