Closed
Description
(Moved from #69098 (comment) with an added PoC.)
The following program (playground) demonstrates how current implementation of target_feature_11
allows using a target_feature from safe code without ensuring it's actually available:
#![feature(target_feature_11)]
#[target_feature(enable="avx")]
fn use_avx() {
println!("Hello from AVX")
}
fn call_it(f: impl FnOnce()) {
f();
}
fn main() {
call_it(use_avx);
}
This is unsound because it allows executing (e.g.) AVX instructions on CPUs that do not implement them, which is UB. It only works because "safe fns with target_features" are erroneously considered to implement the FnOnce/FnMut/Fn traits.
Metadata
Metadata
Assignees
Labels
Area: Enabling/disabling target features like AVX, Neon, etc.Category: This is a bug.target feature 1.1 RFCIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the language teamThis issue requires a nightly compiler in some way.
Activity
petrochenkov commentedon May 8, 2020
Proposed resolution: #69098 (comment).
petrochenkov commentedon May 8, 2020
Or perhaps the RFC should be revised to still require writing
unsafe fn
and only unsafety checker need to be enhanced to allow calling unsafe functions without unsafe blocks in the situations known to be safe.That would be even less magic, which is good, IMO.
The ergonomic regression would be minor because
unsafe
would still be not required at call sites.nikomatsakis commentedon May 8, 2020
Good catch. Another option is that referencing, not calling, a target-feature function is unsafe, but I guess that is a bit inconsistent given that this already compiles (playground):
In other words, accessing a safe target feature 1.1 function would be unsafe (unless the target feature is in scope), not just calling it.
I think that this is what I would expect somehow, but I would expect it to apply uniformly to both safe and unsafe target feature functions (and that's not an option).
The downside of this approach is that we don't know why the function was declared unsafe, not really -- was it only because of the target feature? Or were there additional requirements that would have made it unsafe?
hanna-kruppe commentedon May 8, 2020
For example, a whole bunch of
core::arch::*
functions take raw pointers and use them to access memory, so they need to be unsafe even if the respective target feature is enabled in the calling context.petrochenkov commentedon May 8, 2020
Ah, right, that's a good argument.
The "unsafety checker enhancement" should only affect unsafe functions that are made unsafe through
#[target_feature]
, but not other means (explicitunsafe
orextern
block).19 remaining items