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

Fails with "unsafe precondition(s) violated" since Rust 1.78 #7

Closed
sophie-h opened this issue May 15, 2024 · 7 comments
Closed

Fails with "unsafe precondition(s) violated" since Rust 1.78 #7

sophie-h opened this issue May 15, 2024 · 7 comments
Assignees

Comments

@sophie-h
Copy link
Contributor

heif_context_read_from_reader calls triggers

unsafe precondition(s) violated: slice::from_raw_parts_mut requires the pointer to be aligned and non-null, and the total size of the slice not to exceed isize::MAX

I did not call it directly but used HeifContext::read_from_reader. But I guess the issue here is the design of the slice types used?

rust-lang/rust#123285

@Cykooz
Copy link
Owner

Cykooz commented May 16, 2024

I think that this error is occurred inside the function libheif-rs::reader::read:

unsafe extern "C" fn read(data: *mut c_void, size: usize, user_data: *mut c_void) -> c_int {
    let reader = &mut *(user_data as *mut Box<dyn Reader>);
    let buf = slice::from_raw_parts_mut(data as *mut u8, size);
    match reader.read(buf) {
        Ok(real_size) if real_size == buf.len() => 0,
        _ => 1,
    }
}

It seems like libheif may pass null pointer as the data argument or size that exceed isize::MAX. I will check it.

Could you give me an example of code (and heif-file) to reproduce this error?

@Cykooz Cykooz self-assigned this May 16, 2024
@Cykooz
Copy link
Owner

Cykooz commented May 16, 2024

What architecture were you running the code on when you got this error? Is it 32-bit architecture?

@sophie-h
Copy link
Contributor Author

Not tested on 32bit but my CI started failing for amd64 and aarch64 when updating to Rust 1.78 and my Desktop (amd64) as well.

@sophie-h
Copy link
Contributor Author

I will try to create a minimal reproducer later. The original code is a bit involved.

@sophie-h
Copy link
Contributor Author

pub fn main() {
    let data = std::fs::read("color.avif").unwrap();
    let len = data.len() as u64;
    let stream_reader = libheif_rs::StreamReader::new(std::io::Cursor::new(data), len);

    libheif_rs::HeifContext::read_from_reader(Box::new(stream_reader)).unwrap();
}

It seems to happen with all avif pictures but not heic. For completeness here is an image https://gitlab.gnome.org/sophie-h/test-images/-/blob/main/images/color/color.avif

@Cykooz
Copy link
Owner

Cykooz commented May 16, 2024

I have checked. libheif calls function read() with data=null and size=0.
I believe that this piece of avif-format parser code causes an error in libheif-rs.

https://github.com/strukturag/libheif/blob/e64bb552f5d48fee5daf69c8c2fd59ec3eee0818/libheif/avif.cc#L73-L78

  const size_t configOBUs_bytes = range.get_remaining_bytes();
  m_config_OBUs.resize(configOBUs_bytes);

  if (!range.read(m_config_OBUs.data(), configOBUs_bytes)) {
    // error
  }

Here range is a C++ wrapper for our StreamReader. If his method get_remaining_bytes() returns zero the m_config_OBUs vector will be resized to empty size. In this case a pointer to vector's data will be null.

I've added the handling of this case into read function and release libheif-rs v1.0.2

@sophie-h
Copy link
Contributor Author

Thanks a lot!

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

2 participants