Confusion about RUSTSEC-2018-0010

Hi all, I spent much time figuring out why use-after-free could happen in RUSTSEC-2018-0010 but I am still stuck. Based on the commit, I considered the problem might occur on data_bio_ptr:

// Before
let data_bio_ptr = match data {
    Some(data) => MemBioSlice::new(data)?.as_ptr(),
    None => ptr::null_mut(),
// after
let data_bio = match data {
    Some(data) => Some(MemBioSlice::new(data)?),
    None => None,
let data_bio_ptr = data_bio.as_ref().map_or(ptr::null_mut(), |p| p.as_ptr());

Here, I don't understand why wrapping MemBioSlice::new(data) in Option could solve the problem. I have thought that error might occur at ::new(); however, it will cause to early return by ? and why uaf could happen?

Thanks for reading and would be open to any discussion!

Point is not in wrapping in Option, but in the place where MemBioSlice is dropped.

In the first code snippet, MemBioSlice::new creates a temporary - it is created inside the match arm, then discarded without being assigned to anywhere. Therefore, as_ptr returns the pointer which is immediately invalidated.

In the second case, MemBioSlice::new creates some value which is then stored in data_bio; therefore, as long as data_bio is alive (and not moved) - the corresponding pointer is valid.


In Rust variables are semantically meaningful. Assigning something to a variable changes its lifetime, which can affect behavior of the program and its safety.

In languages with garbage collection let result = foo().bar() and let tmp = foo(); let result = are identical, but they behave differently in Rust.

1 Like

Oh, I see, it is the magic of Rust's ownership system. The scope of ::new(data) was only limited to the match arm. Therefore, when the match arm was finished, what was left in the data_bio_ptr was only a raw pointer to a dropped memory. Then, use-after-free occurred when FFI function tried to access the data_bio_ptr. Is it correct?