Yet another leak in the sinking ship of @safe

Jonathan M Davis via Digitalmars-d digitalmars-d at puremagic.com
Thu Feb 18 11:25:16 PST 2016


On Thursday, 18 February 2016 at 18:58:56 UTC, H. S. Teoh wrote:
> On Thu, Feb 18, 2016 at 06:50:34PM +0000, Jonathan M Davis via 
> Digitalmars-d wrote:
>> On Thursday, 18 February 2016 at 18:41:25 UTC, Steven 
>> Schveighoffer wrote:
> [...]
>> >foo(void[] arr)
>> >{
>> >   void[] arr2 = [1234, 5678, 91011];
>> >   arr[] = arr2[0 .. arr.length];
>> >}
>> 
>> Well, I'm not sure that that's actually not @safe.
>
> How can it possibly be @safe??? Consider:
>
> 	void main() @safe {
> 		Object[] objs = [ new Object() ];
> 		foo(objs);
> 	}
>
> Now the pointer to the Object instance has been corrupted.

Does it matter what state the void[] is in until you actually 
attempt to cast it to something else? If you have

Object[] oArr = [ new Object ];
void[] vArr = oArr;
vArr = vArr[0 .. $ - 1];

it's not like that's going to cause any problems - not by itself. 
As soon as you convert it back to Object[] or to int[] or 
whatever, _then_ you're screwed. But converting from void[] to 
anything is inherently @system regardless of what you did to the 
array or where it came from. Now, given that reducing the length 
like that is setting you up for a bad conversion, I can certainly 
see an argument for reducing the length of a void[] being 
@system, but in and of itself, it isn't going to corrupt memory. 
It just sets the stage for it. As long as it stays void[], 
everything is fine.

Now given that you can't possibly do anything useful with 
reducing the length of void[] and that it does make it so that 
future, @system operations would corrupt memory, I can certainly 
see making it @system, but I dispute that it's really doing 
anything unsafe on its own.

>> It's trying to interpret the void[] that's the problem. 
>> Certainly, you can convert T[] to void[] and pass it around 
>> all day without risking any memory corruption, so that should 
>> definitely be @safe, and I don't see how reducing the length 
>> of a void[] could actually cause memory corruption on its own. 
>> It's when you cast the void[] to something else that you risk 
>> things going south, and that's what needs to be @system. So, 
>> I'm not sure that there's actually any reason for your example 
>> code to not be @safe.
> [...]
>
> I think you missed the point of his example. :-) The point is 
> that it's
> perfectly legal to (1) cast an array of int to void[], and (2) 
> it's also
> perfectly legal to cast an array of anything to void[], and (3) 
> under
> current rules, it's perfectly legal to copy one void[] to 
> another
> void[].
>
> Arguably, (3) should not be allowed in @safe code. Which again 
> brings us back to the point, that if any function takes void[] 
> as an argument, is there *anything* it can do with the void[] 
> other than reading it, that *won't* break @safe?
>
> If there's *nothing* it can legally do with a void[] (other 
> than reading it) without violating @safe, then shouldn't it be 
> a requirement that all functions marked @safe must take 
> const(void)[] rather than void[]?

It could pass it to something else without actually doing 
anything to it, in which case, I don't see why it couldn't be 
@safe. It's interpreting a void[] that's the problem. _That_ 
needs to be @system. Merely converting to void[] or passing it 
around is harmless. And as long as converting void[] to anything 
else is considered @system like it should be, I don't see why it 
would be necessary to care about whether a function accepts 
void[] or not when considering @safety. Useless as it may be

     void[] identity(void[] arr) @safe
     {
         return arr;
     }

is perfectly @safe. If the compiler does its job, and the 
function does cast the void[], then the function will be 
considered @system unless it's marked @trusted, and all is well 
without caring one whit about how the function was passed void[].

The problem with std.socket is not that it accepts void[] and 
considers that @safe; it's that it passes that void[] to 
something else, treating that as @safe, when it's not. And since 
it's a C function that's being called, and it accesses the ptr 
member of the void[], it's already @system, forcing @trusted to 
be used to make the compiler happy. So, the problem is that 
@trusted was used when it shouldn't have been, not that the type 
system allowed void[] to be passed in without marking it as 
@system. And since the function was marked @trusted, it's not 
like having the compiler treat a function that accepted void[] as 
@system would have helped anyway.

- Jonathan M Davis


More information about the Digitalmars-d mailing list