Bug 19831 – throw/catch in scope(exit) crashes with illegal instruction

Status
RESOLVED
Resolution
FIXED
Severity
major
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2019-04-26T14:23:52Z
Last change time
2019-05-16T06:37:30Z
Keywords
EH, pull, safe, wrong-code
Assigned to
No Owner
Creator
FeepingCreature

Comments

Comment #0 by default_357-line — 2019-04-26T14:23:52Z
Since DMD 2.076, the following code crashes with a segfault or illegal instruction: import std.stdio; void foo() { try throw new Exception(""); catch (Exception ex) writefln("got ex %s", ex); } void main() { scope(exit) foo(); writeln("Hello D"); throw new Exception("Foob"); } It worked in all previous versions back to 2.060.
Comment #1 by default_357-line — 2019-05-02T15:29:28Z
As far as I can see, what happens is it tries to format the exception inside foo(), goes into core.demangle.doDemangle, throws a ParseException, forgets how to cope with `catch (ParseException)` and falls right through to `catch (Exception)`, where it assert(false)s out. Why? Who knows. Dark dwarf magic.
Comment #2 by default_357-line — 2019-05-02T15:33:24Z
https://run.dlang.io/is/49cEHl Cleaner repo of the underlying issue.
Comment #3 by default_357-line — 2019-05-03T05:40:03Z
It's exception chaining. It uses the type of the originally thrown exception, even though the exception it's currently looking at has a different type.
Comment #4 by default_357-line — 2019-05-03T06:19:28Z
Note that this leads to potential memory corruption in @safe: https://run.dlang.io/is/rP2yXU And what happens here in detail is that it inspects "current exceptions in flight" to select the type of handler to jump to, see druntime dwarfeh.d getClassInfo, but it doesn't at all account for the fact that an exception may be thrown and caught solely inside the finally handler, never being chained at all. To fix this, exception chaining must only happen after the second exception being thrown passes the finally block originally triggered by the exception it'll be chained to.
Comment #5 by dlang-bot — 2019-05-10T18:14:51Z
@FeepingCreature created dlang/druntime pull request #2602 "Try to fix issue 19831 without understanding by copying the behavior from __dmd_personality_v0" fixing this issue: - Try to fix issue 19831 without understanding by copying the behavior from __dmd_personality_v0 https://github.com/dlang/druntime/pull/2602
Comment #6 by dlang-bot — 2019-05-16T06:37:30Z
dlang/druntime pull request #2602 "Try to fix issue 19831 without understanding by copying the behavior from __dmd_personality_v0" was merged into stable: - 7a3d881525ad856e78a49afa39de5e05ba9f4eda by FeepingCreature: fix issue 19831: select the appropriate exception handler analogously to __dmd_personality_v0 (ignoring in-flight exceptions that we haven't collided with yet) https://github.com/dlang/druntime/pull/2602