Skip to content
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

Undefined Behavior in Db::get_nice_slice due to Unaligned Reference #35

Open
lwz23 opened this issue Dec 5, 2024 · 0 comments
Open

Comments

@lwz23
Copy link

lwz23 commented Dec 5, 2024

Hello, thank you for your contribution in this project, currently I'm scanning unsoundness problem in Rust project and I notice the following code.

let slice: &[u32] = slice::from_raw_parts(ptr, self.raw_data.len() / 4);

pub fn get_nice_slice(&self) -> &[u32] {
        if self.raw_data.len() > 0 {
            unsafe {
                let ptr = self.raw_data.as_ptr() as *const u32;
                let slice: &[u32] = slice::from_raw_parts(ptr, self.raw_data.len() / 4);
                slice
            }
        } else {
            &self.data.data
        }
    }

Description:
The Db::get_nice_slice function in the doublepir_rs crate triggers undefined behavior (UB) when the raw_data in Db is not properly aligned for u32. This occurs because slice::from_raw_parts assumes that the pointer passed to it is correctly aligned for the target type (u32 in this case). However, there is no alignment check in the code before performing the unsafe conversion.

PoC

extern crate doublepir_rs;

use doublepir_rs::database::Db;
use doublepir_rs::params::Params;
fn main() {
  let params=Params{ n: 10, sigma: 10.0, l: 10, m: 10, logq: 10, p: 10 };
  let mut a=Db::new(1, 1, &params);
  a.raw_data=vec![1,2,3];
  let slice = a.get_nice_slice();
  println!("{:?}", slice); 
}

The issue was discovered using cargo miri, which reported the following error:

error: Undefined Behavior: constructing invalid value: encountered an unaligned reference (required 4 byte alignment but found 1)
   --> C:\Users\ROG\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\slice\raw.rs:138:9
    |
138 |         &*ptr::slice_from_raw_parts(data, len)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 4 byte alignment but found 1)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = note: BACKTRACE:
    = note: inside `std::slice::from_raw_parts::<'_, u32>` at C:\Users\ROG\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\slice\raw.rs:138:9: 138:47
    = note: inside `doublepir_rs::database::Db::get_nice_slice` at E:\Github\sdk\lib\doublepir\src\database\database.rs:140:37: 140:88
note: inside `main`
   --> src\main.rs:9:15
    |
9   |   let slice = a.get_nice_slice();
    |               ^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

This code assumes that self.raw_data is:

 let ptr = self.raw_data.as_ptr() as *const u32;
                let slice: &[u32] = slice::from_raw_parts(ptr, self.raw_data.len() / 4);

Properly aligned to a 4-byte boundary required for u32.
Has a length that is a multiple of 4.
However, no checks are performed to ensure these conditions hold, leading to undefined behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant