Fantastic exchange from DConf

Steven Schveighoffer via Digitalmars-d digitalmars-d at puremagic.com
Fri May 19 08:12:20 PDT 2017


On 5/19/17 9:46 AM, Moritz Maxeiner wrote:
> On Friday, 19 May 2017 at 11:53:57 UTC, Steven Schveighoffer wrote:

>> This provides a foundation to build completely @safe libraries.
>
> Agreed if you mean libraries being marked completely as @safe (which I
> assume).
> Disagreed if you mean libraries that are proven to never corrupt memory
> (not possible with unsafe operating system).

I mean libraries which only contain @safe and @system calls.

i.e.:

$ grep -R '@trusted' libsafe | wc -l
0

>> 2. @trusted blocks in any project need to be considered red flags. You
>> should not need to audit @safe code.
>
> Yes you do, because it can call into @trusted like this:
>
> ---
> void foo(int[] bar) @safe
> {
>   () @trusted {
>     // Exploitable code here
>   }();
> }
> ---
>
> You *must* audit third party @safe code for such hidden @trusted code
> (e.g. grep recursively through such third party code for @trusted and
> verify).

This is what I mean by auditing @trusted when it interacts with @safe code.

Using your example, if we confirm that no matter how you call foo, the 
@trusted block cannot break memory safety, then foo becomes a verified 
@safe function. Then any @safe function that calls foo can be considered 
@safe without auditing.

This is actually a necessity, because templates can infer safety, so you 
may not even know the call needs to be audited. The most dangerous thing 
I think is to have @trusted blocks which use templated types.

A real example recently was a PR that added @safe to a function, and 
made the following call:

() @trusted { return CreateDirectoryW(pathname.tempCStringW(), null); }

Where pathname was a range. The trusted block is to allow the call to 
CreateDirectoryW, but inadvertently, you are trusting all the range 
functions inside pathname, whatever that type is!

The correct solution is:

auto cstr = pathname.tempCStringW();
() @trusted { return CreateDirectoryW(cstr, null); }

So yes, if the third party has @trusted code, you need to audit it. But 
once you have audited the *block* of trusted code, and how it interacts 
within its function, you can consider the calling @safe functions 
actually safe without auditing.

>> If we get into "@safe really means @trusted" territory, we have lost.
>
> For code that you write yourself, @safe means @safe, of course. For code
> other people write and you want to call, it being marked @safe does
> really mean @trusted as long as you yourself have not looked inside it
> and verified there either is no hidden @trusted, or verified *yourself*
> that the hidden @trusted is memory safe.
> I consider any other behaviour to be negligent to the degree of "you
> don't actually care about memory safety at all".

I think there will be a good market for separating libraries between 
@trusted-containing libraries, and only @safe-containing libraries. This 
will make the auditing more focused, and more shareable. I don't expect 
people to use Phobos and audit all the @trusted blocks personally. If "D 
is memory safe" means "D is memory safe ONLY if you verify all of the 
standard library personally", we still have lost.

-Steve


More information about the Digitalmars-d mailing list