Bug 12857 – Don't allow declaring @system function inside @safe block

Status
RESOLVED
Resolution
INVALID
Severity
enhancement
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2014-06-05T03:33:00Z
Last change time
2016-06-12T09:58:52Z
Keywords
pull, safe
Assigned to
nobody
Creator
k.hara.pg

Comments

Comment #0 by k.hara.pg — 2014-06-05T03:33:55Z
Because it would break memory safety. See example code: auto func(int n) @safe { static int* ptr; if (!ptr) ptr = new int(n); static void foo() @system { ptr = cast(int*)1; // stomp memory } return &foo; } void main() { auto fp = func(1); func(1); fp(); // break 'ptr' in @safe code func(1); // crash! }
Comment #1 by github-bugzilla — 2014-06-05T05:42:49Z
Commits pushed to master at https://github.com/D-Programming-Language/phobos https://github.com/D-Programming-Language/phobos/commit/0a41eb29e0c34caeedf9530f202f57ce47bddaf5 Supplemental fix for issue 12857 The local template function zeroLen is inferred to @system. So it should not be placed directly under the @safe unittest body. https://github.com/D-Programming-Language/phobos/commit/a4a0cb19646fc193558c25862ef5b87d6b81b39d Merge pull request #2229 from 9rnsr/fix12857 Supplemental fix for issue 12857
Comment #2 by k.hara.pg — 2014-06-05T06:20:53Z
Comment #3 by k.hara.pg — 2014-06-05T09:49:37Z
OK, this is not a corruption of @safe concept. The original code can be rewritten as follows: int* ptr; static void foo() @system { ptr = cast(int*)1; // stomp memory } auto func(int n) @safe { if (!ptr) ptr = new int(n); return &foo; } void main() { ... } And func cannot assume the pointer value won't be corrupted, because someone can corrupt it. But, in original code, the static variable `ptr` is declared inside the safe function. Therefore anyone cannot stomp it from outside of foo. I think that everything inside @safe function should be safe or trusted. From the point of view, declaring @system function inside @safe is much dangerous. By disallowing it, we can stop writing error-prone code.
Comment #4 by code — 2014-06-05T14:03:15Z
(In reply to Kenji Hara from comment #3) > I think that everything inside @safe function should be safe or trusted. > From the point of view, declaring @system function inside @safe is much > dangerous. By disallowing it, we can stop writing error-prone code. I'm opposed to this change as it gratuitously increases language complexity. The current behavior is neither dangerous nor error prone. To see this, consider the following variation of your original example: --- auto func() @safe { static int* ptr; if (!ptr) ptr = new int; *ptr = 42; // Write something to ptr. return &ptr; } void main() { auto pp = func(); func(); *pp = cast(int*)1; func(); // crash! } --- Here, it is clear that it's not returning the pointer from func() that is unsafe, but writing a random value to it in main(). There is nothing that conceptually separates leaking a reference to a value out of a @safe function via a return value or a ref parameter from defining a nested function and passing that on. To put it differently, what is dangerous in your examples is not what happens inside func(), but that you rely on manual, error-prone inspection of main() to evaluate correctness of the program.
Comment #5 by issues.dlang — 2014-06-05T19:38:16Z
Actually, I really don't see a problem here. The unsafe operation is in main. _That_ is where the @system function is called. Sure, the fact that func returns auto makes it harder to see, but if you marked main with @safe, then it would be clear, since the compiler would give then an error when fp was called.
Comment #6 by bugzilla — 2016-06-12T09:58:52Z
See closing of https://github.com/D-Programming-Language/dmd/pull/3623 and the comments here as to why this is invalid.