diff options
| author | John Schmidt <john.schmidt.h@gmail.com> | 2023-02-04 14:42:42 +0100 |
|---|---|---|
| committer | John Schmidt <john.schmidt.h@gmail.com> | 2023-02-04 20:51:15 +0100 |
| commit | b1dd4b17d89633c4d26c39952f69d7ff2efb98ce (patch) | |
| tree | c7aa18ada844a59848fba0b730ee69f04de65ffe /lib/std/json.zig | |
| parent | b42caff2a20eb34073f6a766f55d27288028165a (diff) | |
| download | zig-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.zig | 32 |
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); + } } } }, |
