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

Multiple unsound problems in bcf crate #459

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

Multiple unsound problems in bcf crate #459

lwz23 opened this issue Dec 5, 2024 · 7 comments

Comments

@lwz23
Copy link

lwz23 commented Dec 5, 2024

unsafe { slice::from_raw_parts(self.inner().samples, self.sample_count() as usize) };

Hello, thank you for your contribution in thin project. Currently, I'm scnning rust project in github, and I notice the following code.

pub struct HeaderView {
    pub inner: *mut htslib::bcf_hdr_t,
}

fn inner(&self) -> htslib::bcf_hdr_t {
        unsafe { *self.inner }
    }

 pub fn samples(&self) -> Vec<&[u8]> {
        let names =
            unsafe { slice::from_raw_parts(self.inner().samples, self.sample_count() as usize) };
        names
            .iter()
            .map(|name| unsafe { ffi::CStr::from_ptr(*name).to_bytes() })
            .collect()
    }

Since samples is a pub function, and inner is also a pub field, bcf is also a pub mod. So I guess this might mean that the user can manipulate the value of inner directly, and if inner is set to an eg. null pointer, it might cause UB.

@lwz23
Copy link
Author

lwz23 commented Dec 5, 2024

After some effort, I managed to get the project up and running, and I think I should be able to confirm that there is indeed an unsound problem.
here is my Poc:
Cargo.toml:

[package]
name = "lwz"
version = "0.1.0"
authors = ["lwz"]
edition = "2018"

[dependencies]
rust-htslib = "*"

main.rs:

extern crate rust_htslib;

use std::ptr;

use rust_htslib::bcf::header::HeaderView;


fn main() {
   let a=HeaderView::new(ptr::null_mut());
   let _=a.samples();
}

result:

lwz@LAPTOP-F68E79VH:/mnt/e/Github/lwz$ cargo run
   Compiling hts-sys v2.2.0
   Compiling rust-htslib v0.49.0
   Compiling lwz v0.1.0 (/mnt/e/Github/lwz)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 10.26s
     Running `target/debug/lwz`
Segmentation fault (core dumped)

@lwz23
Copy link
Author

lwz23 commented Dec 7, 2024

maybe same problem for Record's impl group like:

unsafe { slice::from_raw_parts_mut(self.inner.data, self.inner().l_data as usize) };

but I didn't test it, maybe we can also take a look at it ;)

@lwz23
Copy link
Author

lwz23 commented Dec 9, 2024

same problem for

(*(*self.inner).id[htslib::BCF_DT_ID as usize].offset(*id as isize)).key,

(*(*self.inner).id[htslib::BCF_DT_SAMPLE as usize].offset(*id as isize)).key,

let rec = unsafe { &(**(*self.inner).hrec.offset(i as isize)) };

If there is no extern usage for HeaderView, maybe we should mark it as private, at least for its field should be marked as private. And add !null_ptr check in new method

@lwz23 lwz23 changed the title Maybe unsound in samples? Multiple unsound problems in bcf crate Dec 9, 2024
@lwz23
Copy link
Author

lwz23 commented Dec 9, 2024

Same for Recode struct

pub fn inner(&self) -> &htslib::bcf1_t {

pub fn inner_mut(&mut self) -> &mut htslib::bcf1_t {

@lwz23
Copy link
Author

lwz23 commented Dec 10, 2024

ping?

@lwz23
Copy link
Author

lwz23 commented Dec 10, 2024

same for

inner: *mut htslib::bam_hdr_t,

alghough this time the field is not pub, user can still pass null pointer to inner with the new method
pub fn new(inner: *mut htslib::bam_hdr_t) -> Self {

@lwz23
Copy link
Author

lwz23 commented Dec 10, 2024

maybe same problem for

pub fn from_inner(from: *mut htslib::bam1_t) -> Self {

user can pass a null pointer to this function.

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