-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
simd_insert and simd_extract allow garbage data #77477
Comments
This comment has been minimized.
This comment has been minimized.
Yeah the Miri ICE should definitely be fixed. I guess the question is whether these intrinsics should fail to monomorphize, or whether using them with OOB indices is UB. I assume the latter, but it would be good to get someone to confirm... who would know about SIMD stuff? Also, this UB should be added to the docs for those intrinsics, probably in stdarch. |
rust/compiler/rustc_codegen_llvm/src/intrinsic.rs Lines 882 to 902 in 6f56fbd
The rust/compiler/rustc_codegen_llvm/src/intrinsic.rs Lines 915 to 938 in 6f56fbd
|
This comment has been minimized.
This comment has been minimized.
The insert and extract intrinsics do not even have |
That is just an oversight in stdarch. All users of it are constant. (either fixed or using the constify family of macros) |
Well, but codegen does not seem to rely on them being constants either, so why would we require that? |
While LLVM allows variable indexes, it will generate way more efficient code when indexes are known at compile time. https://godbolt.org/z/zvorEa Other codegen backends, like cg_clif, may also not allow variable indexes. |
Sure, having more efficient code when some things are statically known is expected.
I guess this is a question for one or several of the Rust teams then, whether it is reasonable to restrict these intrinsics to compile-time known indices even though supporting run-time indices is possible (and doesn't seem too hard, judging from what LLVM generates). We can either
Cc @rust-lang/project-portable-simd -- this is not really about portable SIMD but hopefully still reaches the right people. |
|
It doesn't require changes to the compiler but, AFAIK, it is only usually added when the compiler requires these constants, and actively exploits that for type checking and/or codegen. |
I don't see a problem with restricting the intrinsics to constant indices now and implementing the necessary code to verify the indices are in bounds. GCC for example has a similar restriction. Once there's an actual known use-case for non-constant indices in these operations we could consider relaxing the operation (while also implementing bound checking similar to one we do when indexing into slices today). |
@jyn514 why did you mark this as I-unsound? Many intrinsics are unsafe to use, that does not make them unsound.
I'd expect the intrinsic to be unchecked, and OOB indexing to be UB -- that is also the case, on the MIR level, with slice indexing today. Bounds checks are added during MIR construction. |
Sorry, I saw 'unsound' in the message description and wasn't thinking. |
None of the |
Assigning |
Not for these two though it seems... And indeed I don't think there is precedent for having such an intrinsic be checked. Instead, what we usually do is expose a safe function to the user which first does the check and then calls the unsafe intrinsic. AFAIK none of the other SIMD intrinsics have any reasonable chance of causing UB (they all just operate on pure values), except for the shuffle intrinsics -- which however require statically known indices to even perform code generation. So that does not tell us anything about the intended behavior of simd_insert and sim_extract. Or are there other intrinsics that could cause UB but have some checks applied to them to avoid that? |
I think this is Rust unsoundness and not just unsound calling code if the intent is that it is not supposed to break in this particular manner.
📞 Hello! Right, where were we? I believe |
Well, looks like the experts agree they should be constant. Fine for me, I was just trying to help explore the design space. :) So looks like the fix here is to add |
|
However, stdarch relies quite heavily on being able to pass non- So we'd have to rearrange things quite a bit if we wanted to enforce the |
There are also 17 functions like this pub unsafe fn _mm256_extract_epi64<const INDEX: i32>(a: __m256i) -> i64 {
static_assert_imm2!(INDEX);
simd_extract(a.as_i64x4(), INDEX as u32)
} Due to the cast, this isn't just "forwarding" the const generic parameter, so we'd either need |
I don't think we should enable an incomplete feature like So how do people here feel about using a macro like this also for |
I feel that these changes are quite intrusive and I would rather avoid them if possible. Could we instead force a const-evaluation on the compiler side where necessary? AFAIK platform intrinsics are not meant to be directly exposed to user, so this shouldn't be a big issue. |
How'd that be different from promotion (which we just -- finally -- got rid of in this context)? |
Longer-term (when Though given that this is an internal-only API, at that point it might make more sense to just change the code to |
It feels somewhat silly to me that the compiler supports arbitrary constant expressions if you wrap them in a complicated dance of associated constants but not if you just write them directly in-line. Would using inline consts work here? |
Oh, that part. Inline consts are supposed to be able to use generics from the environment some day, yes. Different people disagree about whether that should be subject to |
Also, FWIW, even if inline consts supported using generics, that would still not be enough any more once |
is this "can't" a "you can't do it yet" or a "you can't ever do it, it's theoretically impossible" |
It's certainly a "can't do it yet"; no idea what the long-term plans of @rust-lang/project-const-generics are here. |
But all this means is that until this is resolved, we cannot make the For this issue, we probably should focus on making |
It turns out that simd_extract is used by stdarch with non-constant indices: #[simd_test(enable = "altivec")]
unsafe fn test_vec_lde_u16() {
let pat = [u16x8::new(0, 1, 2, 3, 4, 5, 6, 7)];
for off in 0..8 {
let v: u16x8 = transmute(vec_lde(off * 2, pat.as_ptr() as *const u8));
assert_eq!(off as u16, v.extract(off as _));
}
}
@Amanieu @workingjubilee what shall we do with that? |
Does std::arch have internal functions for casting to arrays? That seems like a reasonable alternative, especially in a test. |
I haven't seen such functions. For now I've changed it to use ptr arithmetic. |
…dx, r=oli-obk,Amanieu require simd_insert, simd_extract indices to be constants As discussed in rust-lang#77477 (see in particular [here](rust-lang#77477 (comment))). This PR doesn't touch codegen yet -- the first step is to ensure that the indices are always constants; the second step is to then make use of this fact in backends. Blocked on rust-lang/stdarch#1530 propagating to the rustc repo.
… r=oli-obk check that simd_insert/extract indices are in-bounds Fixes rust-lang#77477 r? `@oli-obk`
Rollup merge of rust-lang#121522 - RalfJung:insert-extract-boundscheck, r=oli-obk check that simd_insert/extract indices are in-bounds Fixes rust-lang#77477 r? `@oli-obk`
…-obk,Amanieu require simd_insert, simd_extract indices to be constants As discussed in rust-lang/rust#77477 (see in particular [here](rust-lang/rust#77477 (comment))). This PR doesn't touch codegen yet -- the first step is to ensure that the indices are always constants; the second step is to then make use of this fact in backends. Blocked on rust-lang/stdarch#1530 propagating to the rustc repo.
check that simd_insert/extract indices are in-bounds Fixes rust-lang/rust#77477 r? `@oli-obk`
…-obk,Amanieu require simd_insert, simd_extract indices to be constants As discussed in rust-lang/rust#77477 (see in particular [here](rust-lang/rust#77477 (comment))). This PR doesn't touch codegen yet -- the first step is to ensure that the indices are always constants; the second step is to then make use of this fact in backends. Blocked on rust-lang/stdarch#1530 propagating to the rustc repo.
…-obk,Amanieu require simd_insert, simd_extract indices to be constants As discussed in rust-lang/rust#77477 (see in particular [here](rust-lang/rust#77477 (comment))). This PR doesn't touch codegen yet -- the first step is to ensure that the indices are always constants; the second step is to then make use of this fact in backends. Blocked on rust-lang/stdarch#1530 propagating to the rustc repo.
It appears that with simd_insert and simd_extract that I can produce garbage data in a way that is probably due to unsound OOB memory access. These are unsafe functions but the related simd_shuffle functions fail to monomorphize. Miri provokes an ICE. I thiiiink simd_extract and simd_insert might not require const arguments on purpose, but I believe something may need to be patched re: Miri. cc @RalfJung
I was in the middle of constructing tests for rustc's simd intrinsics. I tried this code: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=dfc24d97ffa77e6fbd4a65c16b713cf9
I (perhaps overly naively) expected to see this happen: "failure to monomorphize because blah blah blah"
Instead, this happened: I got some totally wild garbage data!
rustc --version
:The Miri ICE:
The text was updated successfully, but these errors were encountered: