How to properly use parseFromSlice()?

Documentation says if arena is passed as an allocator, it’s better to use parseFromSliceLeaky(). I do pass arena, but I don’t have to in this function:

pub fn readFile(io: std.Io, gpa: std.mem.Allocator, path: []const u8) !Reader {
    const file = try std.Io.Dir.cwd().openFile(io, path, .{
        .mode = .read_only,
        .lock = .exclusive,
    });
    defer file.close(io);

    const buf = try gpa.alloc(u8, try file.length(io));
    var reader = file.reader(io, buf);
    // Read all content of a file into buffer
    try reader.interface.readSliceAll(buf);

    var parsed = try std.json.parseFromSlice(
        Config,
        gpa,
        buf,
        .{ .ignore_unknown_fields = true },
    );
    defer parsed.deinit();
    return .{ .config = parsed.value, .buf = buf };
}

I saw that parseFromSlice uses @memcpy() but I wasn’t able to follow it fully. Does adding that defer parsed.deinit() make use-after-free here? I am calling allocator free(reader.buf) to free a buf passed in a return of a struct