On Friday, 19 May 2017 at 15:12:20 UTC, Steven Schveighoffer
wrote:
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
In that case, agreed. There will be no need (with regards to
memory safety) to audit such libraries.
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.
Ok, I was not sure what exactly you meant (because interaction is
a broad concept), so I went explicit as I did not want to assume.
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.
Yes (assuming any such @safe function does not call another
@trusted function that wasn't verified).
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); }
Interesting case. I have not encountered something like it
before, since all code that I mark @trusted uses OS provided
structs, primitive types, or arrays (nothing fancy like ranges).
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.
Indeed (again, though, only if that calling @safe function
doesn't call some other @trusted you forgot to audit).
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.
I totally agree. Unfortunately, most of what I use D for is
replacing C in parts where I have to directly interface with C,
specifically glibc wrapped syscalls.
I considered calling the syscalls directly and completly bypass C
at all, but since syscalls in Linux are often in reality
available in userspace without context switch (vdso), the code is
not trivial and I decided to just use interface with the C
wrappers.
This will make the auditing more focused, and more shareable.
Sure.
I don't expect people to use Phobos and audit all the @trusted
blocks personally.
As long as they don't actually call them, that's reasonable. But
if your application ends up calling @trusted code and you did not
audit that @trusted yourself, you have violated the @trusted
requirement:
You cannot promise to the compiler that the code is memory safe
since you have no knowledge of what it actually does.
If "D is memory safe" means "D is memory safe ONLY if you
verify all of the standard library personally", we still have
lost.
It is more like "D is memory safe" meaning "D is memory safe ONLY
if you verify all of the @trusted code your application end up
compiling in / linking against".
There is no way around that I can see without getting rid of
@trusted, which is impossible for a systems PL.