ref is unsafe

Tommi tommitissari at hotmail.com
Fri Jan 4 06:15:00 PST 2013


On Friday, 4 January 2013 at 06:30:55 UTC, Sönke Ludwig wrote:
> In other words, references returned by a function call that 
> took any references to locals would be
> tainted as possibly local (in the function local data flow) and 
> thus are not allowed to escape the
> scope. References derived from non-local refs could still be 
> returned and returning references to
> fields from a struct method also works.
>
> ---
> @safe ref int test(ref int v) {
> 	return v; // fine
> }
>
> @safe ref int test2() {
> 	int local;
> 	return test(local); // error: (possibly) returning ref to local
> }
>
> @safe ref int test3() {
> 	int local;
> 	int* ptr = &test(local); // fine, ptr is tainted 'local'
> 	return *ptr; // error: (possibly) returning ref to local
> }
>
> @safe ref int test4(ref int val) {
> 	return test(val); // fine, can only be a ref to the external 
> 'val' or to a global
> }
> ---

Trying to say that formally:

Definitions:
'Tainter function':
     A function that:
     1. takes at least one of its parameters by reference
     and
     2. returns by reference
	
'Tainting function call':
     A call to a 'tainter function' where at least one of the
     arguments passed by reference is ref to a local variable

Then the rules become:
Function may not return a reference to:
Rule 1: a function-local variable
Rule 2. a value returned by a 'tainting function call'

@safe:

ref int tfun(ref int v) { // tfun tagged 'tainter function'
     ...
}

ref int test1() {
     int local;
     return local; // error by Rule 1
}

ref int test2() {
     int local;
     return tfun(local); // error by Rule 2
}

ref int test3() {
     int local;
     int* ptr = &tfun(local); // ptr tagged 'local'
     return *ptr; // error by Rule 2
}

ref int test4(ref int val) {
     return tfun(val); // fine
}

int global;

ref int test5() {
     int local;
     int* ptr = &tfun(local); // ptr tagged 'local'
     ptr = &global; // ptr's 'local' tag removed
     return *ptr; // fine
}


More information about the Digitalmars-d mailing list