Closed
Description
This is a wasm target, built with -fwasm-exceptions
. Reproducer:
#include <cstdio>
__attribute__((noinline)) void print_current() noexcept {
try {
throw;
} catch (int x) {
printf("%d\n", x);
}
}
struct Dropper {
~Dropper() {
try {
throw 1;
} catch (...) {
print_current();
}
}
};
int main() {
try {
Dropper dropper;
throw 2;
} catch (...) {
print_current();
}
}
Expected output: 1 2
, actual output: 1 1
.
(I'm using emcc -O2 -fwasm-exceptions test.cpp
for testing if that's important.)
The problem is in the codegen for main
:
Wasm IR
(func (;6;) (type 11) (result i32)
(local i32 i32)
global.get 0
local.set 1
call 22
local.tee 0
i32.const 2
i32.store
try ;; label = @1
local.get 0
call 28
catch_all
local.get 1
global.set 0
call 22
local.tee 0
i32.const 1
i32.store
try ;; label = @2
try ;; label = @3
local.get 0
call 28
catch 0
local.set 0
local.get 1
global.set 0
local.get 0
call 29
drop
call 5
call 30
try ;; label = @4
try ;; label = @5
rethrow 2 (;@3;)
catch 0
local.set 0
local.get 1
global.set 0
local.get 0
call 29
drop
call 5
try ;; label = @6
call 30
delegate 5
i32.const 0
return
end
unreachable
delegate 3
unreachable
end
catch_all
local.get 1
global.set 0
call 37
unreachable
end
unreachable
end
unreachable
)
In pseudocode, simplified:
try:
throw(2)
catch_all:
try:
try:
throw(1)
catch:
print_current()
rethrow(0)
catch:
print_current()
So rethrow(0)
rethrows the same exception as has just been handled, so the same exception object is caught twice. rethrow(2)
would work correctly. The current behavior leads to all sorts of memory corruption and hard-to-debug state.