fix memory leak on string arguments

This commit is contained in:
Luna 2022-04-27 20:01:00 -03:00
parent b195577dee
commit d7d4385242
2 changed files with 20 additions and 5 deletions

View file

@ -479,6 +479,21 @@ pub const CommandList = struct {
pub fn deinit(self: *Self) void { pub fn deinit(self: *Self) void {
for (self.list.items) |cmd_ptr| { for (self.list.items) |cmd_ptr| {
self.list.allocator.destroy(cmd_ptr); self.list.allocator.destroy(cmd_ptr);
inline for (@typeInfo(Command.Tag).Enum.fields) |field| {
if (cmd_ptr.tag == @field(Command.Tag, field.name)) {
const actual_tag =
@field(Command.Tag, field.name);
// if we find a match on the tag, we can get the type
const typ = Command.tagToType(actual_tag);
inline for (@typeInfo(typ).Struct.fields) |cmd_field| {
switch (cmd_field.field_type) {
[]u8, []const u8 => self.list.allocator.destroy(@field(typ, cmd_field.name)),
else => {},
}
}
}
}
} }
self.list.deinit(); self.list.deinit();
} }
@ -561,7 +576,7 @@ pub const Lang = struct {
f32 => try std.fmt.parseFloat(f32, arg), f32 => try std.fmt.parseFloat(f32, arg),
u64 => try std.fmt.parseInt(u64, arg, 10), u64 => try std.fmt.parseInt(u64, arg, 10),
usize => try std.fmt.parseInt(usize, arg, 10), usize => try std.fmt.parseInt(usize, arg, 10),
[]const u8 => arg, []const u8 => @as([]const u8, try self.allocator.dupe(u8, arg)),
else => @compileError("parameter struct has unsupported type " ++ @typeName(cmd_field.field_type)), else => @compileError("parameter struct has unsupported type " ++ @typeName(cmd_field.field_type)),
}; };
@ -586,7 +601,7 @@ pub const Lang = struct {
usize => try std.fmt.parseInt(usize, arg, 10), usize => try std.fmt.parseInt(usize, arg, 10),
i32 => try std.fmt.parseInt(i32, arg, 10), i32 => try std.fmt.parseInt(i32, arg, 10),
f32 => try std.fmt.parseFloat(f32, arg), f32 => try std.fmt.parseFloat(f32, arg),
[]const u8 => arg, []const u8 => @as([]const u8, try self.allocator.dupe(u8, arg)),
else => @compileError("Invalid parameter type (" ++ @typeName(cmd_field.field_type) ++ ") left on command struct " ++ @typeName(command_struct) ++ "."), else => @compileError("Invalid parameter type (" ++ @typeName(cmd_field.field_type) ++ ") left on command struct " ++ @typeName(command_struct) ++ "."),
}; };

View file

@ -40,6 +40,8 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: anytype) !void {
var stdout_file = std.io.getStdOut(); var stdout_file = std.io.getStdOut();
const stdout = &stdout_file.writer(); const stdout = &stdout_file.writer();
const scri_path = try (args_it.next(allocator) orelse @panic("expected scri path")); const scri_path = try (args_it.next(allocator) orelse @panic("expected scri path"));
errdefer allocator.free(scri_path);
defer allocator.free(scri_path);
var file_read_opt: ?std.fs.File = std.fs.cwd().openFile(scri_path, .{}) catch |err| blk: { var file_read_opt: ?std.fs.File = std.fs.cwd().openFile(scri_path, .{}) catch |err| blk: {
if (err == error.FileNotFound) break :blk null; if (err == error.FileNotFound) break :blk null;
@ -54,11 +56,9 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: anytype) !void {
defer lang.deinit(); defer lang.deinit();
if (total_bytes > 0) { if (total_bytes > 0) {
// this MUST BE long lived (a reference to it is kept inside
// existing_cmds, and then passed along to cmds),
// we can't defer them here
var scri_existing = try allocator.alloc(u8, total_bytes); var scri_existing = try allocator.alloc(u8, total_bytes);
_ = try file_read_opt.?.read(scri_existing); _ = try file_read_opt.?.read(scri_existing);
defer allocator.free(scri_existing);
// we can't defer this directly because we copy the // we can't defer this directly because we copy the
// Command pointers to the cmds list. running deinit() directly // Command pointers to the cmds list. running deinit() directly