Koka / odbc-rs

Rust ODBC FFI binding
MIT License
103 stars 31 forks source link

Unsound implementation of `convert_primitive` #174

Open shinmao opened 1 year ago

shinmao commented 1 year ago

The source of unsoundness

Hi, we are the researchers from Sun Security Lab. With our bug detector, we found that convert_primitive might have an unsound implementation. https://github.com/Koka/odbc-rs/blob/f9e5f77fac0a6328f9759e6e0f9e10c16509aebb/src/statement/types.rs#L281-L286 At line 285, buf is aligned to 1 byte, and it can be cast to other types with stricter alignment requirement. If misaligned pointer is passed to from_raw_parts, it could cause to undefined behavior in this safe function.

To reproduce the bug

use odbc::*;

fn main() {
    let a: [u8; 4] = [12; 4];
    let b = u32::convert(&a);
    println!("{:?}", b);
}

In this case, convert will call from_raw_parts(x.as_ptr() as *const u32, 1) which has a misaligned pointer.

fn main() {
    let a: [u8; 2] = [12; 2];
    let b = f64::convert(&a);
    println!("{:?}", b);
}

run with miri

error: Undefined Behavior: dereferencing pointer failed: alloc1303 has size 2, so pointer to 4 bytes starting at offset 0 is out-of-bounds
   --> /${HOME}/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/raw.rs:100:9
    |
100 |         &*ptr::slice_from_raw_parts(data, len)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: alloc1303 has size 2, so pointer to 4 bytes starting at offset 0 is out-of-bounds

In this case, the length of the buffer is only 2 bytes. However, from_raw_parts expects 8 bytes to be read.

shinmao commented 1 year ago

[UPDATED] There is another unsound implementation in convert: https://github.com/Koka/odbc-rs/blob/f9e5f77fac0a6328f9759e6e0f9e10c16509aebb/src/statement/types.rs#L139-L142 which also create a misaligned pointer and passed to from_raw_parts.