diff options
author | Björn Gustavsson <[email protected]> | 2019-05-23 07:22:41 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2019-05-23 10:12:23 +0200 |
commit | 5959fb00182048d50f55d04684723d383d1aeee8 (patch) | |
tree | f01d55472255bf60398116eb719ede79dae4011c /erts/emulator/beam/instrs.tab | |
parent | 7fe7fa3dde556b5b92522f8279d465bb52baf1f6 (diff) | |
download | otp-5959fb00182048d50f55d04684723d383d1aeee8.tar.gz otp-5959fb00182048d50f55d04684723d383d1aeee8.tar.bz2 otp-5959fb00182048d50f55d04684723d383d1aeee8.zip |
Fix sticky class in exception
When catching an exception re-throwing with a changed
class, the class could be changed to the original class
if the exception got caught and rethrown in (for example)
an after block:
sticky_class() ->
try
try
throw(reason)
catch
throw:Reason:Stack ->
erlang:raise(error, Reason, Stack)
end
after
ok
end.
Diffstat (limited to 'erts/emulator/beam/instrs.tab')
-rw-r--r-- | erts/emulator/beam/instrs.tab | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/erts/emulator/beam/instrs.tab b/erts/emulator/beam/instrs.tab index 42c1168f85..999e9337ff 100644 --- a/erts/emulator/beam/instrs.tab +++ b/erts/emulator/beam/instrs.tab @@ -951,19 +951,30 @@ raw_raise() { Eterm class = x(0); Eterm value = x(1); Eterm stacktrace = x(2); + Eterm* freason_ptr; + + /* + * Note that the i_raise instruction will override c_p->freason + * with the freason field stored inside the StackTrace struct in + * ftrace. Therefore, we must take care to store the class both + * inside the StackTrace struct and in c_p->freason (important if + * the class is different from the class of the original + * exception). + */ + freason_ptr = get_freason_ptr_from_exc(stacktrace); if (class == am_error) { - c_p->freason = EXC_ERROR & ~EXF_SAVETRACE; + *freason_ptr = c_p->freason = EXC_ERROR & ~EXF_SAVETRACE; c_p->fvalue = value; c_p->ftrace = stacktrace; goto find_func_info; } else if (class == am_exit) { - c_p->freason = EXC_EXIT & ~EXF_SAVETRACE; + *freason_ptr = c_p->freason = EXC_EXIT & ~EXF_SAVETRACE; c_p->fvalue = value; c_p->ftrace = stacktrace; goto find_func_info; } else if (class == am_throw) { - c_p->freason = EXC_THROWN & ~EXF_SAVETRACE; + *freason_ptr = c_p->freason = EXC_THROWN & ~EXF_SAVETRACE; c_p->fvalue = value; c_p->ftrace = stacktrace; goto find_func_info; |