-
Notifications
You must be signed in to change notification settings - Fork 13.6k
CFI: Fix types that implement Fn, FnMut, or FnOnce #144936
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
base: master
Are you sure you want to change the base?
Conversation
r? @SparrowLii rustbot has assigned @SparrowLii. Use |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Fix type transformation for types that implement Fn, FnMut, or FnOnce traits (such as Box<dyn Fn()>, Box<dyn FnMut()>, etc.) by transforming self into a trait object of the trait that defines the method.
8b21653
to
bb63853
Compare
This comment has been minimized.
This comment has been minimized.
bb63853
to
8df6ab8
Compare
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.
I'd like to see more explanation for the fix in this PR. Specifically, the issue and the PR don't actually describe what kind of CFI violation was being encountered here before, or how it's being fixed by this erasure?
The comment in #144641 (comment) mentions:
The only special handling in the code is for closures, coroutines, and coroutine closures, but not for arbitrary types that implement these traits.
Does this make the code that is special-cased for closure-like types redundant?
let fn_traits = [ | ||
(LangItem::Fn, sym::call), | ||
(LangItem::FnMut, sym::call_mut), | ||
(LangItem::FnOnce, sym::call_once), | ||
]; | ||
for (lang_item, method_sym) in fn_traits { | ||
if let Some(trait_id) = tcx.lang_items().get(lang_item) { | ||
let items = tcx.associated_items(trait_id); | ||
if let Some(call_method) = | ||
items.in_definition_order().find(|item| item.name() == method_sym) | ||
{ |
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.
This logic does a ton of unnecessary work.
Just compute if let Some(trait_def_id) = tcx.trait_of_assoc(instance.def_id())
, use tcx.as_lang_item()
to turn it into a LangItem
, and match on Fn
/FnMut
/FnOnce
.
if let Some(call_method) = | ||
items.in_definition_order().find(|item| item.name() == method_sym) | ||
{ | ||
if instance.def_id() == call_method.def_id { |
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.
What kind of InstanceKind
are we expecting here? This seems like it would perhaps overlap or interact with the logic above what you added, which seems problematic.
@maurer wrote a lot of this erasure logic, I'd be interested if he has a take on this approach as well |
My first reaction here is that I think this is a bug in |
Specifically, d5bf25c seems to address this more simply - basically, it looks like I missed Update: It looks like the adjustment I'm proposing would also cause:
This looks OK to me, and has the added benefit of automatically picking up new shim types when added. If we wanted to be more conservative, we could instead do 0026b9c which fixes the tests in question with a minimal change - it only re-normalizes |
@maurer Thank you for your time looking at it! Much appreciated. I'm wondering whether we should change approach in this code and cover each case explicitly (like we do for encoding) so we could express our intent clearly and know when something is handled (or not) and the side effects of it (also clearly). |
I added a commit message at https://github.com/maurer/rust/tree/cfi-fix - I hadn't bothered because I just expected you to squash it onto your commit if you agreed with the direction. Re: being more explicit with casing out, I think maybe the way to do that (which should definitely be a future PR if at all) would be:
I don't know how much maintenance this saves us, mostly depends on how often we're sprinkling new |
Fix type transformation for types that implement Fn, FnMut, or FnOnce traits (such as Box<dyn Fn()>, Box<dyn FnMut()>, etc.) by transforming self into a trait object of the trait that defines the method. Fixes #144641.
cc @1c3t3a @Jakob-Koschel