Issue 21981 - Manually calling a __dtor can violate memory safety
Summary: Manually calling a __dtor can violate memory safety
Status: NEW
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P4 enhancement
Assignee: No Owner
URL:
Keywords:
: 22507 (view as issue list)
Depends on:
Blocks:
 
Reported: 2021-05-26 21:59 UTC by thomas.bockman
Modified: 2022-12-17 10:31 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description thomas.bockman 2021-05-26 21:59:50 UTC
The purpose of destructors is to describe cleanup work to be performed when the lifetime of an object is over. Allowing @safe code to call a destructor manually before that point and then continue to use the destroyed object afterwards breaks RAII memory management:

/////////////////////////////////////////////
module app;

import core.stdc.stdlib : malloc, free;

struct UniqueInt {
    private int* target;
    this(const(bool) doCreate) scope @trusted nothrow @nogc {
        target = cast(int*) malloc(int.sizeof);
        *target = 5;
    }
    @disable this(this);
    @disable this(ref typeof(this));
    @disable ref typeof(this) opAssign(ref typeof(this));

    void withBorrow(void delegate(scope int*) @safe action) @safe {
        action(target); }

    ~this() scope @trusted nothrow @nogc {
        if(target !is null) {
            free(target);
            target = null;
        }
    }
}

UniqueInt unique;
shared static this() {
    unique = true; }

void main() @safe {
    import std.stdio: writeln;

    unique.withBorrow((scope int* borrowed) @safe {
        writeln(*borrowed);
        destroy(unique);
        writeln(*borrowed); // Use after free.
    });
}
/////////////////////////////////////////////

I think the only reasonable solution to this is to make calling __dtor, __xdtor, or destroy manually an @system operation, regardless of the attributes of ~this().

(I suspect there is some way to violate memory safety or break the type system with this even in 100% @safe code, but I couldn't figure out what it is so I've marked this as an enhancement request.)

Forum thread:
    https://forum.dlang.org/post/tkxneqmsbxfpomlnekhv@forum.dlang.org
Comment 1 Dennis 2021-11-12 16:51:21 UTC
*** Issue 22507 has been marked as a duplicate of this issue. ***