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