aboutsummaryrefslogtreecommitdiff
path: root/lib/std/json.zig
diff options
context:
space:
mode:
authorJohn Schmidt <john.schmidt.h@gmail.com>2023-02-04 14:42:42 +0100
committerJohn Schmidt <john.schmidt.h@gmail.com>2023-02-04 20:51:15 +0100
commitb1dd4b17d89633c4d26c39952f69d7ff2efb98ce (patch)
treec7aa18ada844a59848fba0b730ee69f04de65ffe /lib/std/json.zig
parentb42caff2a20eb34073f6a766f55d27288028165a (diff)
downloadzig-b1dd4b17d89633c4d26c39952f69d7ff2efb98ce.tar.gz
zig-b1dd4b17d89633c4d26c39952f69d7ff2efb98ce.zip
std.json: don't free struct default values
Closes https://github.com/ziglang/zig/issues/9509.
Diffstat (limited to 'lib/std/json.zig')
-rw-r--r--lib/std/json.zig32
1 files changed, 31 insertions, 1 deletions
diff --git a/lib/std/json.zig b/lib/std/json.zig
index 1c4cbdf5cb..42c4d98d32 100644
--- a/lib/std/json.zig
+++ b/lib/std/json.zig
@@ -1745,7 +1745,37 @@ pub fn parseFree(comptime T: type, value: T, options: ParseOptions) void {
.Struct => |structInfo| {
inline for (structInfo.fields) |field| {
if (!field.is_comptime) {
- parseFree(field.type, @field(value, field.name), options);
+ var should_free = true;
+ if (field.default_value) |default| {
+ switch (@typeInfo(field.type)) {
+ // We must not attempt to free pointers to struct default values
+ .Pointer => |fieldPtrInfo| {
+ const field_value = @field(value, field.name);
+ const field_ptr = switch (fieldPtrInfo.size) {
+ .One => field_value,
+ .Slice => field_value.ptr,
+ else => unreachable, // Other pointer types are not parseable
+ };
+ const field_addr = @ptrToInt(field_ptr);
+
+ const casted_default = @ptrCast(*const field.type, @alignCast(@alignOf(field.type), default)).*;
+ const default_ptr = switch (fieldPtrInfo.size) {
+ .One => casted_default,
+ .Slice => casted_default.ptr,
+ else => unreachable, // Other pointer types are not parseable
+ };
+ const default_addr = @ptrToInt(default_ptr);
+
+ if (field_addr == default_addr) {
+ should_free = false;
+ }
+ },
+ else => {},
+ }
+ }
+ if (should_free) {
+ parseFree(field.type, @field(value, field.name), options);
+ }
}
}
},