Thread overview | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
March 29, 2017 [Issue 17284] std.experimental.typecons.Final allows bypassing @safe on unions | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=17284 hsteoh@quickfur.ath.cx changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |safe Severity|enhancement |normal -- |
March 29, 2017 [Issue 17284] opDispatch allows bypassing @safe on unions | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=17284 ZombineDev <petar.p.kirov@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |petar.p.kirov@gmail.com Component|phobos |dmd Hardware|x86_64 |All Summary|std.experimental.typecons.F |opDispatch allows bypassing |inal allows bypassing @safe |@safe on unions |on unions | OS|Linux |All Severity|normal |major --- Comment #1 from ZombineDev <petar.p.kirov@gmail.com> --- The issue has little to do with std.experimental.typecons.Final. Final just uses std.typecons.Proxy. I added an assert(0) on line 5585 in std.typecons from dmd 2.073.2 and got this: $ ./main core.exception.AssertError@/home/zlx/dlang/dmd-2.073.2/linux/bin64/../../src/phobos/std/typecons.d(5585): Assertion failure ---------------- ??:? _d_assert [0x4296e4] ??:? pure nothrow ref @property @nogc return @safe int std.experimental.typecons.Final!(main.U).Final.__mixin8.opDispatch!("i").opDispatch!(std.experimental.typecons.Final!(main.U).Final).opDispatch() [0x428684] ??:? _Dmain [0x42845b] ??:? _D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFZv [0x429c9f] ??:? void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate()) [0x429bc7] ??:? void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).runAll() [0x429c44] ??:? void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate()) [0x429bc7] ??:? _d_run_main [0x429b33] ??:? main [0x42871f] ??:? __libc_start_main [0x4b801f44] (dmd-2.073.2)/mnt/d/tmp_code/final_safe This issue can easily be reproduced with the following code: class C { } union U { C c; int i; } struct S(T) { private T value__; @property auto ref opDispatch(string name)() { return mixin("value__." ~ name); } } void main() @safe { S!U u; u.c = new C; // compiles (!!!) u.i++; // uh-oh } Therefore I'm changing the component to dmd. -- |
March 29, 2017 [Issue 17284] ref returning function template allows bypassing @safe on unions | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=17284 ZombineDev <petar.p.kirov@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Summary|opDispatch allows bypassing |ref returning function |@safe on unions |template allows bypassing | |@safe on unions --- Comment #2 from ZombineDev <petar.p.kirov@gmail.com> --- I reduced it a bit further: Case 1: ``` class C { } union U { C c; int i; } ref C getC1(ref U u) { return u.c; } ref C getC2(T)(ref T u) { return u.c; } void main() @safe { U u; u.getC2() = new C; // compiles (!!!) } ``` Case 2: ``` class C { } union U { C c; int i; } ref C getC1(ref U u) { return u.c; } ref C getC2(T)(ref T u) { return u.c; } void main() @safe { U u; u.getC1() = new C; // (Line 12) Doesn't compile } ``` main.d(12): Error: @safe function 'D main' cannot call @system function 'main.getC1' Case 3: ``` class C { } union U { C c; int i; } @safe: ref C getC1(ref U u) { return u.c; } // (Line 9) ref C getC2(T)(ref T u) { return u.c; } void main() @safe { U u; u.getC1() = new C; } ``` main.d(9): Error: field U.c cannot access pointers in @safe code that overlap other fields Case 4: ``` class C { } union U { C c; int i; } @safe: ref C getC1(ref U u) { return u.c; } // (Line 9) ref C getC2(T)(ref T u) { return u.c; } // (Line 10) void main() @safe { U u; u.getC2() = new C; // (Line 14) } ``` main.d(9): Error: field U.c cannot access pointers in @safe code that overlap other fields main.d(10): Error: field U.c cannot access pointers in @safe code that overlap other fields main.d(14): Error: template instance main.getC2!(U) error instantiating -- |
March 29, 2017 [Issue 17284] ref returning function template allows bypassing @safe on unions | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=17284 --- Comment #3 from ZombineDev <petar.p.kirov@gmail.com> --- So it seems that the bug has to do with the @safe-ty inference on template functions, since the code does not compile if the function template is explicitly marked with @safe. -- |
March 29, 2017 [Issue 17284] ref returning function template allows bypassing @safe on unions | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=17284 --- Comment #4 from hsteoh@quickfur.ath.cx --- Interesting. So it would appear that the problem is caused by attribute inference wrongly inferring @safe for a template function that returns an overlapping pointer field. I.e.: ---- class C { } union U { C c; int i; } ref C func(T)(ref T t) { return t.c; } pragma(msg, typeof(func!U)); ---- Compiler output: ---- pure nothrow @nogc ref @safe C(return ref U t) ---- The correct inferred type should be: ---- pure nothrow @nogc ref @system C(return ref U t) ---- -- |
March 29, 2017 [Issue 17284] Template function attribute inference wrongly infers @safe for accessing overlapping pointer fields in unions | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=17284 hsteoh@quickfur.ath.cx changed: What |Removed |Added ---------------------------------------------------------------------------- Summary|ref returning function |Template function attribute |template allows bypassing |inference wrongly infers |@safe on unions |@safe for accessing | |overlapping pointer fields | |in unions -- |
March 29, 2017 [Issue 17284] Template function attribute inference wrongly infers @safe for accessing overlapping pointer fields in unions | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=17284 --- Comment #5 from hsteoh@quickfur.ath.cx --- Oh my, it gets worse: ref has nothing to do with it at all! Look at this blatant violation of @safe: ------ class C { } union U { C c; int i; } void func(T)(T t) { t.c = new C; t.i++; // !!! } pragma(msg, typeof(func!U)); ------ Compiler output: ------ pure nothrow @safe void(U t) ------ Looks like attribute inference is a free license to violate @safety. :-D Or, more precisely, attribute inference completely forgets to check for overlapping pointers. -- |
March 29, 2017 [Issue 17284] Template function attribute inference wrongly infers @safe for accessing overlapping pointer fields in unions | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=17284 --- Comment #6 from ZombineDev <petar.p.kirov@gmail.com> --- > Looks like attribute inference is a free license to violate @safety. :-D Yeah with templates one enters 'god mode' in :D Though the situation isn't very clear-cut. Take this code for example: ``` struct S { int* ptr; } void func1()() { S s; s.ptr++; } pragma (msg, "typeof(&func1!()): ", typeof(&func1!())); class C { } union U { C c; int i; } void func2()() { U u; u.c = null; } pragma (msg, "typeof(&func2!()): ", typeof(&func2!())); int[] func3()() { int[5] sa; return sa; } pragma (msg, "typeof(&func3!()): ", typeof(&func3!())); int[] func4a(int[] a) @safe { return a; } int[] func4b()() { int[5] sa; return func4a(sa); } pragma (msg, "typeof(&func4b!()): ", typeof(&func4b!())); void main() {} ``` $ dmd safe_infer_test1.d typeof(&func1!()): void function() pure nothrow @nogc @system typeof(&func2!()): void function() pure nothrow @nogc @safe typeof(&func3!()): safe_infer_test1.d(10): Error: escaping reference to local variable sa int[] function() pure nothrow @nogc @safe typeof(&func4b!()): int[] function() @safe So, depending on the code in question, sometimes inferences works correctly, and sometimes not. Also note that the attribute inference of func4b!() changes depending on if you compile with -dip1000 or not: $ dmd -dip1000 safe_infer_test1.d typeof(&func1!()): void function() pure nothrow @nogc @system typeof(&func2!()): void function() pure nothrow @nogc @safe typeof(&func3!()): safe_infer_test1.d(10): Error: escaping reference to local variable sa int[] function() pure nothrow @nogc @safe typeof(&func4b!()): int[] function() @system -- |
January 20, 2018 [Issue 17284] Template function attribute inference wrongly infers @safe for accessing overlapping pointer fields in unions | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=17284 Carsten Blüggel <chilli@posteo.net> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |chilli@posteo.net -- |
March 04, 2018 [Issue 17284] Template function attribute inference wrongly infers @safe for accessing overlapping pointer fields in unions | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=17284 Walter Bright <bugzilla@digitalmars.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |bugzilla@digitalmars.com --- Comment #7 from Walter Bright <bugzilla@digitalmars.com> --- https://github.com/dlang/dmd/pull/7982 -- |
Copyright © 1999-2021 by the D Language Foundation