I want to use Rust raw pointer like *const
to reproduce the security problem of use after free, but when I use the raw pointer to access fields or call the function of a freed struct variable, there's no panic occurred.
Here's my codes:
new
method is used to create the struct more conveniently. as_ptr
method is used to return the raw pointer of the struct itself.
pub struct Foo{
data: Vec<u8>,
}
impl Foo{
pub fn new(data: &[u8]) -> Foo{
Foo{ data: data.to_vec() }
}
pub fn as_ptr(&self) -> *const Foo{
// return a raw pointer of this struct
self as *const Foo
}
pub fn test(&self){
println!("test");
}
}
test
method above and use_raw_ptr
method below are intended to reproduce the use after free problem.
pub unsafe fn use_raw_ptr(ptr: *const Foo){
println!("{:?}", (*ptr).data);
}
When testing, I create a Foo
struct variable foo
in match
blocks, which I suppose should be the scope of the foo
variable. Then the raw pointer of foo
is passed to p
if data
is legal. After match
block, I try to use p
to call the function test
of Foo
and access data
field of foo
, where I suppose use after free problem should appear because foo
should be freed already.
fn main(){
let data: Option<&[u8]> = Some(b"abc");
let p = match data{
Some(data) => {
let foo = Foo::new(data);
foo.as_ptr();
}
None => std::ptr::null(),
};
unsafe {(*p).test()};
println!("{:?}", data);
unsafe{ use_raw_ptr(p) };
}
However, no panic occurrs when executing the codes and here's the output:
test
Some([97, 98, 99])
[192, 230, 41]
It also should be mentioned that the result of use_raw_ptr
differs everytime I run the codes, but the length of printed result always match the input data. I wonder if this is because when foo
is freed, some information like the length of data
is still remained?
fn main(){
let data: Option<&[u8]> = Some(b"abcde");
// ... same as above
}
// output
test
Some([97, 98, 99, 100, 101])
[192, 230, 5, 252, 49]
Besides, I think that the reason of the succecc call of unsafe{(*p).test()}
is that it calls the function of Foo
struct instead of foo
variable. I don't know if this is corrent and I'm wondering if I can make program panic here using raw pointer to access freed memory.
Dereferencing a dangling pointer is undefined behaviour. Undefined behaviour is, well undefined meaning that you cannot expect any behaviour, exepecting it to panic is therefore not valid.
Or in other words, any behaviour including but not limited to not changing the memory and therefore the values still being in the same memory locations, panicing, setting the pc on fire, executing a game of Doom™ is possible.