-
Notifications
You must be signed in to change notification settings - Fork 296
Description
Right now we override the error callbacks at compile time with:
rust-secp256k1/secp256k1-sys/src/lib.rs
Lines 364 to 369 in c6ab14b
pub unsafe extern "C" fn rustsecp256k1_v0_1_1_default_illegal_callback_fn(message: *const c_char, _data: *mut c_void) { | |
use core::str; | |
let msg_slice = slice::from_raw_parts(message as *const u8, strlen(message)); | |
let msg = str::from_utf8_unchecked(msg_slice); | |
panic!("[libsecp256k1] illegal argument. {}", msg); | |
} |
rust-secp256k1/secp256k1-sys/src/lib.rs
Lines 387 to 392 in c6ab14b
pub unsafe extern "C" fn rustsecp256k1_v0_1_1_default_error_callback_fn(message: *const c_char, _data: *mut c_void) { | |
use core::str; | |
let msg_slice = slice::from_raw_parts(message as *const u8, strlen(message)); | |
let msg = str::from_utf8_unchecked(msg_slice); | |
panic!("[libsecp256k1] internal consistency check failed {}", msg); | |
} |
But this is sadly UB if the panic strategy is unwind
(the default):
Calling a function with the wrong call ABI or unwinding from a function with the wrong unwind ABI.
https://doc.rust-lang.org/reference/behavior-considered-undefined.html
You must absolutely catch any panics at the FFI boundary
https://doc.rust-lang.org/nomicon/unwinding.html
Now the easiest solution is to replace the panic with abort, but then we have a few problems:
- We lose the printing, the user just gets a
Aborted (core dumped)
orIllegal instruction (core dumped)
which makes it very hard to pinpoint (We could conditionally print ifstd
is on, but that sucks). - Which
abort
do we call?
2.a. The libc one?(adds the assumption of libc which might break for wasm).
2.b. The intrinsic one? (requires nightly).
2.c.std::process::abort
? requires libstd.
2.d. Stabilizeintrinsics::abort
incore
rust-lang/rfcs#2512
Another potential solutions:
- Advise users to use
panic=abort
(imo this isn't a good solution). - Conditionally use
std::panic::catch_unwind
which will catch the panic ifstd
is on but will still print the output and/or stacktrace. - Wait for
"C unwind"
which allows unwinding the stack through C. (https://github.com/rust-lang/project-ffi-unwind/blob/master/rfcs/0000-c-unwind-abi.md) - Wait for Add
#[cfg(panic = '...')]
rust-lang/rust#74754 which allows to condition on ifpanic=abort
or not. - Dive deep into the machinery of
panic
and see if we can still trigger printing but abort instead, probably won't be possible in stable. - Propose new language features to fix this(i.e.
abort!(...)
), but even if they'll get accepted we won't use that release for a long time.
(Thanks to @joshtriplett for some of the suggestions)