Fix leaks and double-frees in Kym VM environment
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details

This commit is contained in:
kayomn 2023-06-04 02:39:57 +00:00
parent 08785b5b54
commit 331d862246
1 changed files with 26 additions and 33 deletions

View File

@ -69,21 +69,6 @@ const Object = struct {
self.ref_count += 1; self.ref_count += 1;
} }
pub fn release(self: *Object, env: *Self) bool {
coral.debug.assert(self.ref_count != 0);
self.ref_count -= 1;
if (self.ref_count == 0) {
coral.io.deallocate(env.allocator, self.state.userdata);
self.state.fields.deinit(env.allocator);
return false;
}
return true;
}
}; };
pub const ObjectInfo = struct { pub const ObjectInfo = struct {
@ -185,14 +170,7 @@ pub fn check(self: *Self, condition: bool, failure_message: []const u8) !void {
} }
pub fn deinit(self: *Self) void { pub fn deinit(self: *Self) void {
var global_data = self.heap.fetch(self.global_object); self.discard(.{.object = self.global_object});
if (global_data.release(self)) {
self.heap.remove(self.global_object);
} else {
self.heap.assign(self.global_object, global_data);
}
self.values.deinit(self.allocator); self.values.deinit(self.allocator);
self.calls.deinit(self.allocator); self.calls.deinit(self.allocator);
self.heap.deinit(self.allocator); self.heap.deinit(self.allocator);
@ -203,7 +181,19 @@ pub fn discard(self: *Self, val: types.Val) void {
.object => |object| { .object => |object| {
var data = self.heap.fetch(object); var data = self.heap.fetch(object);
if (data.release(self)) { coral.debug.assert(data.ref_count != 0);
data.ref_count -= 1;
if (data.ref_count == 0) {
data.state.info.deinitializer(.{
.env = self,
.obj = val.as_ref(),
});
coral.io.deallocate(self.allocator, data.state.userdata);
data.state.fields.deinit(self.allocator);
self.heap.remove(object); self.heap.remove(object);
} else { } else {
self.heap.assign(object, data); self.heap.assign(object, data);
@ -223,17 +213,21 @@ pub fn execute_data(self: *Self, source: DataSource) types.RuntimeError!types.Va
} }
}; };
var chunk = try Chunk.init(self, source.name); var compiled_chunk = init_compiled_chunk: {
var chunk = try Chunk.init(self, source.name);
errdefer chunk.deinit(); errdefer chunk.deinit();
chunk.compile(source.data) catch |compile_error| { chunk.compile(source.data) catch |compile_error| {
self.reporter.invoke(chunk.error_details()); self.reporter.invoke(chunk.error_details());
return compile_error; return compile_error;
};
break: init_compiled_chunk chunk;
}; };
const script = try self.new_object(coral.io.bytes_of(&chunk), .{ const script = try self.new_object(coral.io.bytes_of(&compiled_chunk), .{
.identity = typeid, .identity = typeid,
.deinitializer = Behaviors.deinitialize, .deinitializer = Behaviors.deinitialize,
}); });
@ -355,12 +349,11 @@ pub fn native_cast(self: *Self, castable: types.Ref, id: *const anyopaque, compt
try self.check(castable == .object, "invalid type conversion: object"); try self.check(castable == .object, "invalid type conversion: object");
const object = self.heap.fetch(castable.object); const object = self.heap.fetch(castable.object);
const alignment = @alignOf(Type); const is_expected_type = (object.state.info.identity == id) and (object.state.userdata.len == @sizeOf(Type));
const is_expected_type = (object.state.info.identity == id) and (object.state.userdata.len == alignment);
try self.check(is_expected_type, "invalid object cast: native type"); try self.check(is_expected_type, "invalid object cast: native type");
return @ptrCast(*Type, @alignCast(alignment, object.state.userdata)); return @ptrCast(*Type, @alignCast(@alignOf(Type), object.state.userdata));
} }
pub fn new_array(self: *Self) coral.io.AllocationError!types.Val { pub fn new_array(self: *Self) coral.io.AllocationError!types.Val {