Skip to content

Potential unsoundness in unsafe_casts::any_as_u8_slice due to struct padding #1

@lewismosciski

Description

@lewismosciski

Hello,

First, thank you for your work on the borrowck_sacrifices crate. It's a very interesting exploration of Rust's borrow capabilities.

Our team is currently developing a static analysis tool for Rust, and during our testing, we believe we have identified a potential soundness issue in the unsafe_casts::any_as_u8_slice function.

pub fn any_as_u8_slice<'a,T: Sized>(p: &'a T) -> &'a [u8] {
unsafe{
::core::slice::from_raw_parts((p as *const T) as *const u8, ::core::mem::size_of::<T>())
}
}

It appears that any_as_u8_slice can create a byte slice (&[u8]) that references uninitialized memory when used with types that contain padding bytes. According to the Rustonomicon and the official documentation for slice::from_raw_parts, creating a reference to uninitialized memory is Undefined Behavior.

POC:

use borrowck_sacrifices::unsafe_casts::any_as_u8_slice;

struct MyStruct {
    _a: u8,  
    _b: u32,
}

fn main() {
    let h = MyStruct { _a: 1, _b: 2 };
    let bytes: &[u8] = any_as_u8_slice(&h);
    println!("{:?}", bytes);
}

Verified with miri:

ccuu@ccuu-H3CDesk-D500t:~/Desktop/rust/test1$ cargo +nightly miri run
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.02s
     Running `/home/ccuu/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/cargo-miri runner target/miri/x86_64-unknown-linux-gnu/debug/test1`
error: Undefined Behavior: reading memory at alloc130[0x5..0x6], but memory is uninitialized at [0x5..0x6], and this operation requires initialized memory
   --> /home/ccuu/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/num.rs:599:5
    |
599 |     impl_Display!(i8, u8, i16, u16, i32, u32, i64, u64, isize, usize; as u64 into display_u64);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior

Perhaps the most direct fix is to change the function signature to pub unsafe fn any_as_u8_slice .... This would make the API contract honest about its potential dangers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions