-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use catch_unwind to prevent panicking across FFI. #25
Conversation
Panicking across FFI is undefined behavior, so each of our exported functions must use catch_unwind and return an error (if an error result is possible) or a default value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! The only things that occur to me (and I'm not sure how to do either, or whether either is possible) are:
- is there a way to define perhaps an attribute macro that could be applied to functions that would automatically wrap their bodies in
ffi_panic_boundary_*
, without requiring the indentation of the whole function body? - is there a way to ensure that new functions added to
crustls
will be appropriately wrapped with affi_panic_boundary_*
macro?
This is appealing! I would like to avoid the extra indentation. After reading up, it sounds like attribute macros are a type of procedural macro: https://doc.rust-lang.org/reference/procedural-macros.html#attribute-macros
Whereas what I'm defining here with macro_rules is a "macro by example:" https://doc.rust-lang.org/reference/macros-by-example.html
It sounds like procedural macros are more powerful, and also more complex, than macros. I'd rather stick with the simplicity of what I've got here and pay the (small) price of excess indentation.
I've asked around and heard a few ideas, from static analysis of the code to control flow analysis of a compiled binary. I think for now I'll settle for a script that greps for |
By the way, @tgeoghegan you had asked in chat why the repetition operator #[macro_export]
macro_rules! boundary {
($tokentree:tt) => {
$tokentree
};
}
fn main() {
boundary! {{
let mut x = 1;
x += 2;
println!("{}", x);
}}
} But note that I needed to surround the affected code with an extra layer of braces (
That's not a single tokenTree, it's 6 tokens (each of which can be its own tokenTree). But this:
Is a single tokenTree that contains 6 tokens. |
That's pretty trippy, but it makes sense. Thanks for doing the research. And FWIW I agree with your other conclusions about avoiding procedural macros and static analysis. |
Panicking across FFI is undefined behavior, so each of our exported
functions must use catch_unwind and return an error (if an error result
is possible) or a default value.