incorrect use of unsafe
BurntSushi opened this issue · 4 comments
Most of the functions in hw.rs
either need to be marked unsafe, or guarateed by the type system to be safe. Neither are true today.
From the std::arch
docs:
The CPU the program is currently running on supports the function being called. For example it is unsafe to call an AVX2 function on a CPU that doesn't actually support AVX2.
The simplest way that I can tell to fix this in your code is to create a type that can only be constructed when the correct target features are enabled. e.g.,
struct SSE42(());
impl SSE42 {
fn new() -> Option<SSE42> {
if is_x86_feature_detected!("sse4.2") {
Some(SSE42(()))
} else {
None
}
}
}
Then any function needing to use SSE4.2 can require a SSE42
parameter. And your crc32c_append
function then looks like this:
pub fn crc32c_append(crc: u32, data: &[u8]) -> u32 {
if let Some(receipt) = SSE42::new() {
hw::crc32c(receipt, crc, data)
} else {
sw::crc32c(crc, data)
}
}
The reason why the code today is wrong is because any user of hw.rs
can call hw::crc32c
as a safe function without actually verifying the assumptions required by the use of unsafe
inside hw::crc32c
.
Now, it is true that this is not exposed in the public crate API, which is good. But internally, this is still a violation of unsafe
.
Thanks for the feedback.
The entire point of the crate is to make the determination of software vs. hardware and abstract that via the top-level func. I'll admit there is some internal mess around unsafe, which I'll address.
I'm not sure I follow why a top-level type is necessary in this case. Could you elaborate as to why your proposed SSE42
type is necessary?
My suggestion is one possible solution. What's necessary is to ensure that you do not define a safe function that can be called that doesn't satisfy the assumptions that its use of unsafe
requires.
Another possible solution is to make every function that transitively uses intrinsics in std::arch
unsafe, with the exception of your public functions, which are themselves responsible for satisfying the assumptions that std::arch
requires.
Gotcha. That was my initial thought on fixing the unsafe behavior.