@trusted assumptions about @safe code

ag0aep6g anonymous at example.com
Wed May 27 17:02:15 UTC 2020


On 27.05.20 18:04, Paul Backus wrote:
> On Wednesday, 27 May 2020 at 15:14:17 UTC, ag0aep6g wrote:
[...]
>> From your previous post I figured that this is your position towards 
>> calling @safe from @trusted:
>>
>>     @trusted code is not allowed to rely on the documented
>>     return value of an @safe function. The @trusted function
>>     must instead verify that the actually returned value is
>>     safe to use.
> 
> This is my position on *any* function calling *any other* function. Even 
> in 100% @system code, I must (for example) check the return value of 
> malloc if I want to rely on it not being null.
> 
>> I'm not sure if I'm representing you correctly, but that position 
>> makes sense to me. At the same time, it doesn't seem feasible, because 
>> I don't see how we're going to get users to adhere to that.
> 
> Why does it not seem feasible? Checking return values is defensive 
> programming 101. People already do this sort of thing all the time.

I think we're on the same page for the most part, but not here.

I'm pretty sure that you agree with this: When we call C's strlen like 
so: `strlen("foo\0".ptr)`, we can assume that the result will be 3, 
because strlen is documented to behave that way.

I'm not sure where you stand on this: If an @safe function is documented 
to return 42, can we rely on that in the same way we can rely on 
strlen's documented behavior? Let's say that the author of the @safe is 
as trustworthy as the C standard library.

If we can assume 42, a bug in @safe code can lead to memory corruption 
by breaking an assumption that is in @trusted/@system code. Just like a 
bug in @system code can have that same effect. This might be obviously 
true to you. But I hadn't really made that connection until recently. So 
if you agree with this, then I think we're on the same page now. And we 
just accept that a mistake in @safe code can possibly kill safety.

On the other side, if we cannot assume that 42 being returned, but we 
need to check that 42 was indeed returned, then the weird scenario 
happens where an @safe `my_strlen` becomes more cumbersome to use than 
C's @system `strlen`. I don't think any existing @trusted code was 
written with that in mind.

If I'm not making any sense, maybe we can compare our answers to the 
question whether the following snippets (copied from earlier) can really 
be @trusted.

I think this one is fine:

----
void f() @trusted
{
     import core.stdc.string: strlen;
     import std.stdio: writeln;
     char[5] buf = "foo\0\0";
     char last_char = buf.ptr[strlen(buf.ptr) - 1];
     writeln(last_char);
}
----

And I think this one is fine, too:

----
size_t my_strlen(ref char[5] buf) @safe
{
     foreach (i; 0 .. buf.length) if (buf[i] == '\0') return i;
     return buf.length;
}
void f() @trusted
{
     import std.stdio: writeln;
     char[5] buf = "foo\0\0";
     char last_char = buf.ptr[my_strlen(buf) - 1];
     writeln(last_char);
}
----


More information about the Digitalmars-d mailing list