I have a small C code which demonstrate Runtime Stack functionality by modifying data at a stack address.
#include <stdio.h>
int * fun() {
int a = 10;
return &a;
}
int * fun2() {
int b = 20;
return &b;
}
int main () {
int *a = fun();
int *b = fun2();
printf("a:%d b:%d\n", *a, *b);
return 0;
}
Output of this is : a:20 b:20 which shows 'b' in 'fun2' used the same stack address as 'a' in 'fun'.
i want to test this in Rust too. What would be the simplest way to do this?
I tried Borrowing but compiler says "No value to borrow".
If you want to have the same undefined behavior as in C, you can do (luckily, this requires unsafe
):
fn fun() -> *const i32 {
let a = 10;
&a
}
fn fun2() -> *const i32 {
let b = 20;
&b
}
fn main() {
let a = fun();
let b = fun2();
// SAFETY: Don't do this. This is pure Undefined Behavior.
unsafe {
println!("a: {} b: {}", *a, *b);
}
}
And this is UB exactly as with the C version. It prints a: 21885 b: 21885
on the playground on debug mode, and a: -482758656 b: 32767
on release mode. Yours will be different.
If you also want the same result as the C version, you can use printf()
. Be careful with the code you use, changes can cause it to no longer "work" as it will use a different stack layout. Of course, this is very fragile:
use std::ffi::c_char;
fn fun() -> *const i32 {
let a = 10;
&a
}
fn fun2() -> *const i32 {
let a = 20;
&a
}
extern "C" {
fn printf(format: *const c_char, ...);
}
fn main() {
let a = fun();
let b = fun2();
unsafe {
printf(b"a: %d b: %d\n\0" as *const u8 as *const c_char, *a, *b);
}
}
It prints a: 20 b: 20
on debug mode, and a: 1 b: 1
on release (and yours may be different).