-
-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Hello,
We are developing a static analysis tool for Rust, and our tool flagged a potential soundness issue in the public safe function index_of_ptr.
orx-pinned-vec/src/utils/slice.rs
Lines 32 to 39 in 3f2cfa7
| pub fn index_of_ptr<T>(slice: &[T], element_ptr: *const T) -> Option<usize> { | |
| let element_ptr = element_ptr as usize; | |
| let ptr = slice.as_ptr(); | |
| let ptr_beg = ptr as usize; | |
| if element_ptr < ptr_beg { | |
| None | |
| } else { | |
| let ptr_end = (unsafe { ptr.add(slice.len() - 1) }) as usize; |
The function appears to cause Undefined Behavior when called with an empty slice. The line ptr.add(slice.len() - 1) underflows when slice.len() is 0. According to Rust's safety rules, creating a pointer with such a massive offset is immediate UB, which violates the core guarantee that a safe function cannot cause UB on any input.
This was confirmed with cargo miri. We've included the PoC and Miri's output below for your reference.
POC:
use orx_pinned_vec::utils::slice::index_of_ptr;
fn main() {
let slice: &[u8] = &[];
let ptr_to_check = slice.as_ptr();
let _ = index_of_ptr(slice, ptr_to_check);
}Miri's output:
ccuu@ccuu:~/rust/rtest/nnl_test$ cargo +nightly miri run --release
Finished `release` profile [optimized] target(s) in 0.01s
Running `/home/ccuu/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/cargo-miri runner target/miri/x86_64-unknown-linux-gnu/release/nnl_test`
warning: Miri does not support optimizations: the opt-level is ignored. The only effect of selecting a Cargo profile that enables optimizations (such as --release) is to apply its remaining settings, such as whether debug assertions and overflow checks are enabled.
error: Undefined Behavior: overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize`
--> /home/ccuu/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/orx-pinned-vec-3.10.0/src/utils/slice.rs:39:33
|
39 | let ptr_end = (unsafe { ptr.add(slice.len() - 1) }) as usize;
| ^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `orx_pinned_vec::utils::slice::index_of_ptr::<u8>` at /home/ccuu/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/orx-pinned-vec-3.10.0/src/utils/slice.rs:39:33: 39:57
note: inside `main`
--> src/main.rs:5:13
|
5 | let _ = index_of_ptr(slice, ptr_to_check);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error; 1 warning emitted
A simple check such as if slice.is_empty() { return None; } at the beginning of the function could be a potential fix for this soundness hole.
Thank you for your time and for maintaining this library.