Skip to content

Commit

Permalink
Insert CheckRefs after calling destructors
Browse files Browse the repository at this point in the history
Destructors may leak references of "self" through mutable references
stored in "self". For example, a value storing a `mut Array[mut X]`
could leak "self" (provided it's of type X) by pushing "self" into said
array.

To solve this we now insert the CheckRefs instruction _after_ calling a
destructor. For correct programs this won't make a difference, while
incorrect programs _may_ perform some redundant work in a destructor
before terminating with a panic.

This fixes https://gitlab.com/inko-lang/inko/-/issues/254.

Changelog: fixed
  • Loading branch information
yorickpeterse committed Oct 22, 2022
1 parent 0054f4f commit c362caf
Showing 1 changed file with 6 additions and 2 deletions.
8 changes: 6 additions & 2 deletions compiler/src/mir/passes.rs
Expand Up @@ -517,6 +517,11 @@ impl<'a> GenerateDropper<'a> {
lower.current_block_mut().move_result(res, loc);
}

// We check the ref count _after_ running the destructor, as otherwise a
// destructor might leak references of "self" through other mutable
// references (e.g. a field containing a mutable Array reference).
lower.current_block_mut().check_refs(self_reg, loc);

for field in self.class.id.fields(lower.db()) {
let typ = field.value_type(lower.db());

Expand Down Expand Up @@ -4610,11 +4615,10 @@ impl<'a> ExpandDrop<'a> {
dropper: bool,
location: LocationId,
) {
self.block_mut(before_id).check_refs(value, location);

if dropper {
self.call_dropper(before_id, value, location);
} else {
self.block_mut(before_id).check_refs(value, location);
self.block_mut(before_id).free(value, location);
}

Expand Down

0 comments on commit c362caf

Please sign in to comment.