-
Notifications
You must be signed in to change notification settings - Fork 305
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 ifstdis on, but that sucks). - Which
abortdo 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::abortincorerust-lang/rfcs#2512
Another potential solutions:
- Advise users to use
panic=abort(imo this isn't a good solution). - Conditionally use
std::panic::catch_unwindwhich will catch the panic ifstdis 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=abortor not. - Dive deep into the machinery of
panicand 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)