Skip to content

Commit f35bebc

Browse files
committed
fix(settings): dupe all strings on first-run to prevent Bus error in deinit
When settings.json does not exist (first run), the FileNotFound branch returned a Settings struct with comptime string constants from default (e.g. preferred_mirror = "", proxy = ""). Since deinit() unconditionally calls allocator.free() on these fields, the GPA attempted to write @Memset on read-only memory, causing a Bus error at exit. Dupe all string fields via allocator in the FileNotFound branch so every string is heap-allocated and safe to free in deinit. Also show active Zig version after successful upgrade.
1 parent c6b47c6 commit f35bebc

2 files changed

Lines changed: 35 additions & 3 deletions

File tree

src/settings.zig

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,19 @@ pub const Settings = struct {
5656
pub fn load(allocator: std.mem.Allocator, io: std.Io, path: []const u8) !Settings {
5757
const file = std.Io.Dir.cwd().openFile(io, path, .{}) catch |err| switch (err) {
5858
error.FileNotFound => {
59-
// Create new settings file with defaults
60-
var settings = default;
61-
settings.path = path;
59+
// Create new settings file with defaults.
60+
// Dupe all string fields so deinit can safely free them all.
61+
var settings = Settings{
62+
.version_map_url = try allocator.dupe(u8, default.version_map_url),
63+
.zls_vmu = try allocator.dupe(u8, default.zls_vmu),
64+
.mirror_list_url = try allocator.dupe(u8, default.mirror_list_url),
65+
.use_color = default.use_color,
66+
.always_force_install = default.always_force_install,
67+
.preferred_mirror = try allocator.dupe(u8, default.preferred_mirror),
68+
.mirror_updated_at = default.mirror_updated_at,
69+
.proxy = try allocator.dupe(u8, default.proxy),
70+
.path = path,
71+
};
6272
try settings.save(allocator, io);
6373
return settings;
6474
},

src/upgrade.zig

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,28 @@ pub fn run(
317317
try stdout.print("Now running zvm {s}\n", .{latest_version});
318318
try stdout.flush();
319319

320+
// Show the active Zig version
321+
if (zvm.getActiveVersion(allocator)) |active| {
322+
defer allocator.free(active);
323+
var ver_buf: [std.fs.max_path_bytes]u8 = undefined;
324+
const ver_path = zvm.versionPath(&ver_buf, active);
325+
const zig_path = std.fmt.allocPrint(allocator, "{s}/zig", .{ver_path}) catch return;
326+
defer allocator.free(zig_path);
327+
328+
const ver_result = std.process.run(allocator, zvm.io, .{
329+
.argv = &.{ zig_path, "version" },
330+
.stdout_limit = .limited(1024),
331+
}) catch return;
332+
defer allocator.free(ver_result.stdout);
333+
defer allocator.free(ver_result.stderr);
334+
335+
if (ver_result.stdout.len > 0) {
336+
const ver = std.mem.trim(u8, ver_result.stdout, " \n\r");
337+
try stdout.print("Active Zig: {s} ({s})\n", .{ active, ver });
338+
try stdout.flush();
339+
}
340+
}
341+
320342
// Clean up the downloaded archive
321343
std.Io.Dir.cwd().deleteFile(zvm.io, archive_path) catch {};
322344
}

0 commit comments

Comments
 (0)