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;...@@ -1163,11 +1163,12 @@ const ArrayList = std.ArrayList;
1163const StringArrayHashMap = std.StringArrayHashMap;1163const StringArrayHashMap = std.StringArrayHashMap;
11641164
1165pub const ValueTree = struct {1165pub const ValueTree = struct {
1166 arena: ArenaAllocator,1166 arena: *ArenaAllocator,
1167 root: Value,1167 root: Value,
11681168
1169 pub fn deinit(self: *ValueTree) void {1169 pub fn deinit(self: *ValueTree) void {
1170 self.arena.deinit();1170 self.arena.deinit();
1171 self.arena.child_allocator.destroy(self.arena);
1171 }1172 }
1172};1173};
11731174
...@@ -1809,8 +1810,12 @@ pub const Parser = struct {...@@ -1809,8 +1810,12 @@ pub const Parser = struct {
1809 pub fn parse(p: *Parser, input: []const u8) !ValueTree {1810 pub fn parse(p: *Parser, input: []const u8) !ValueTree {
1810 var s = TokenStream.init(input);1811 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);
1813 errdefer arena.deinit();1817 errdefer arena.deinit();
1818
1814 const allocator = arena.allocator();1819 const allocator = arena.allocator();
18151820
1816 while (try s.next()) |token| {1821 while (try s.next()) |token| {
lib/std/json/test.zig+18
...@@ -2589,6 +2589,24 @@ test "parsing empty string gives appropriate error" {...@@ -2589,6 +2589,24 @@ test "parsing empty string gives appropriate error" {
2589 try testing.expectError(error.UnexpectedEndOfJson, testParse(arena_allocator.allocator(), ""));2589 try testing.expectError(error.UnexpectedEndOfJson, testParse(arena_allocator.allocator(), ""));
2590}2590}
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
2592test "integer after float has proper type" {2610test "integer after float has proper type" {
2593 var arena_allocator = std.heap.ArenaAllocator.init(std.testing.allocator);2611 var arena_allocator = std.heap.ArenaAllocator.init(std.testing.allocator);
2594 defer arena_allocator.deinit();2612 defer arena_allocator.deinit();