Thread overview
[Issue 18598] cyclic constructor calls have undefined behavior but are accepted in @safe code
Mar 20, 2018
Walter Bright
Mar 20, 2018
ag0aep6g
Mar 21, 2018
Walter Bright
Mar 25, 2018
ag0aep6g
Mar 26, 2018
Carsten Blüggel
Dec 17, 2022
Iain Buclaw
May 09, 2023
RazvanN
March 20, 2018
https://issues.dlang.org/show_bug.cgi?id=18598

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bugzilla@digitalmars.com

--- Comment #1 from Walter Bright <bugzilla@digitalmars.com> ---
I don't know a way to assign defined behavior to overflowing the stack :-(

This can, however, be statically detected by the compiler by keeping track of the calls between constructors. (They can't be virtual, so that'll work as long as all the constructor bodies are visible to the compiler.)

--
March 20, 2018
https://issues.dlang.org/show_bug.cgi?id=18598

--- Comment #2 from ag0aep6g <ag0aep6g@gmail.com> ---
(In reply to Walter Bright from comment #1)
> I don't know a way to assign defined behavior to overflowing the stack :-(

Is that a problem for normal (non-constructor) functions as well?

----
void f() @safe { g(); }
void g() @safe { f(); }
void main() @safe { f(); } /* Undefined behavior? */
----

--
March 21, 2018
https://issues.dlang.org/show_bug.cgi?id=18598

--- Comment #3 from Walter Bright <bugzilla@digitalmars.com> ---
(In reply to ag0aep6g from comment #2)
> Is that a problem for normal (non-constructor) functions as well?

Yes.

I'm open to advice on what to do about it.

--
March 25, 2018
https://issues.dlang.org/show_bug.cgi?id=18598

--- Comment #4 from ag0aep6g <ag0aep6g@gmail.com> ---
(In reply to Walter Bright from comment #3)
> I'm open to advice on what to do about it.

I'm by no means an expert here, but don't we have a guaranteed guard page beyond the stack? If we have, stack overflow is guaranteed to fail with a segfault, as long as the access doesn't jump over guard page (cf. issue 17566).

The situation is very similar to null dereferences then. A null dereference also hits a guard page, as long as the offset from null isn't too large (cf. issue 5176).

In both cases, the compiler has to detect offsets that are so large that they would jump over the guard page, and then it has to inject code that makes an earlier access to trigger the segfault. If I got the term right, for the stack that's called "stack probing".

--
March 26, 2018
https://issues.dlang.org/show_bug.cgi?id=18598

Carsten Blüggel <chilli@posteo.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |chilli@posteo.net

--
December 17, 2022
https://issues.dlang.org/show_bug.cgi?id=18598

Iain Buclaw <ibuclaw@gdcproject.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P1                          |P3

--
May 09, 2023
https://issues.dlang.org/show_bug.cgi?id=18598

RazvanN <razvan.nitu1305@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |razvan.nitu1305@gmail.com

--- Comment #5 from RazvanN <razvan.nitu1305@gmail.com> ---
Well, infinite recursion also leads to a segfault due to stack overflow however it is still accepted in @safe code [1]. @safe typically refers to undefined behavior caused by memory corruption. I don't see any memory corruption happening here, since the OS guards against that, rather a programming mistake that is beyond of what the @safe checking mechanism can discover.

[1]  void fun() @safe { fun();

--