D not considered memory safe

Steven Schveighoffer schveiguy at gmail.com
Sat Jul 13 20:37:35 UTC 2024


On Thursday, 11 July 2024 at 16:26:59 UTC, Walter Bright wrote:
> On 7/9/2024 8:58 AM, Nick Treleaven wrote:
>> Any pattern to subvert safe involves the `@trusted` attribute 
>> (except for compiler bugs, which editions help to fix). 
>> `@trusted` is an obvious flag in code review that 
>> memory-safety may be violated. Grepping for `@trusted` is an 
>> easy way to narrow down places where memory-safety is violated.
>> 
>> Arguing that @trusted can be abused is a tiny problem compared 
>> to the far harder to detect abuse in @system by default code.
>
> That's right. Converting an entire program to @safe can be done 
> successfully by doing it incrementally, getting it to pass its 
> test suite at each step. The way to do it incrementally is to 
> start by labeling each function @trusted, then making them 
> @safe one by one.
>
> I've done this, it works.
>
> And, as you observe, grepping for "@trusted" makes for a 
> builtin-in TODO list!

This is not the right approach. You start with marking things 
`@safe` that are leaves, and then move up. Leave things as 
`@system` until you can mark them as `@safe`.

And all templates should be unmarked.

Marking everything `@trusted` at first is just going to end in 
disaster.

When I converted mysql-native to have a `@safe` interface, I 
would start by marking the module `@safe:` at the top, and see 
what breaks. Then I would mark code `@system` that was not safe, 
and see if I could massage it into being `@safe`. I never marked 
anything `@trusted` unless I could prove that it had a safe 
interface.

In some cases, marking `@safe:` at the top does work! But it 
needs to be [a module with no templates in 
it](https://github.com/mysql-d/mysql-native/blob/57fbc2b61aa93dccc11b2f45d3ae23552fd1fdff/source/mysql/impl/connection.d#L32). In many cases, after finding all the safety problems, I had to mark selective pieces as `@safe`.

In my case, the largest problem with my code was using `Variant` 
which cannot be safe. I sure as hell could not mark all of 
variant trusted, as it's in Phobos, and it's also *not safe*.

Another problem with marking `@safe:` at the top, and bludgeoning 
your way through with `@trusted` marks is that you will end up 
marking actual `@system` code as `@trusted`, when it doesn't need 
to be. You only need the *edge* of the safety barrier to be 
marked as trusted.

And finally, if you mark everything trusted, and then find out 
later "oh, this actually cannot be made safe", then all of a 
sudden you might have to mark it as system, and now it cascades 
to a bunch of other things that you thought were already marked 
safe, and now those have to be marked system, and so on. Worst 
case scenario, you have external code depending on the 
trustedness, and now you break other people's code!

My recommendation is to use `@safe:` at the top to *find* where 
you need to address safety problems, and then handle one item at 
a time, marking `@safe`, `@trusted` or `@system` as appropriate. 
Then remove the top line (if it's not all safe).

-Steve


More information about the Digitalmars-d mailing list