0

Consider this pseudocode:

    let k = 10;
    let ptr = &k as *const k;
    println!("{:p}", ptr); // prints address of pointer
    let addr = format!("{:p}", ptr);

    super-unsafe {
    // this would obviously be super unsafe. It may even cause a STATUS_ACCESS_VIOLATION if you try getting memory from a page that the OS didn't allocate to the program!

    let ptr_gen = PointerFactory::from_str(addr.as_str()); 

    assert_eq!(k, *ptr_gen);
    }

The pseudocode gets the idea across: I want to be able to get a pointer to a certain memory address by its &str representation. Is this... possible?

Thomas Braun
  • 505
  • 3
  • 14
  • Why can't you just turn the string representation back to an unsigned integer first? – Peter Varo Jul 16 '19 at 16:17
  • Ah, would this be done via transmute or something under std::mem or std::ptr? – Thomas Braun Jul 16 '19 at 16:26
  • Also, please correct me if I'm wrong as I learn low-level coding, but aren't all pointers the same size in memory unto themselves? (needed to know how many bits to use for unsigned) – Thomas Braun Jul 16 '19 at 16:27
  • 2
    The essentials here are answered in [here](https://stackoverflow.com/questions/32381414/converting-a-hexadecimal-string-to-a-decimal-integer), using `from_str_radix()` to convert e.g. "0xdeadbeef" to an integer; from there you cast to a ptr* and hope nobody is looking – user2722968 Jul 16 '19 at 16:34

1 Answers1

1

So essentially what you want to do is parse the string back to an integer (usize) and then interpret that value as a pointer/reference:

fn main()
{
    let i = 12i32;
    let r = format!("{:p}", &i);


    let x = unsafe
    {
        let r = r.trim_start_matches("0x");
        &*(usize::from_str_radix(&r, 16).unwrap() as *const i32)
    };

    println!("{}", x);
}

You can try this yourself in the playground.

As you can see, you don't even need to cast your reference into a raw pointer, the {:p} formatter takes care of representing it as a memory location (index).


Update: As E_net4 mentioned this in the comment section, it is better to use usize here, which is architecture defined unlike the machine sized one. The transmute was not necessary, so I removed it. The third point about undefined behaviour however seems obvious to whomever tries to do something like the above. This answer provides a way to achieve what the OP asked for which doesn't mean this should be used for anything else than academic/experimental purposes :)

Peter Varo
  • 11,726
  • 7
  • 55
  • 77
  • 1
    Thank you! I'm glad we have this answered on SO now. Although it's not unexpected when rust is using magnum over a baloon for protection. – Thomas Braun Jul 16 '19 at 16:58
  • 1
    No worries, really, but be careful whatever you are going to use it for! (I warned you ;)) Also, I rejected your edit, because that is not helping the understanding IMO. I would suggest you to post it as a separate answer if you like. – Peter Varo Jul 16 '19 at 17:10
  • With mutexes, and some graphs, I'm sure I'll be able to pull out before anything unwanted happens ;). Thank you, and no probs with the edit. – Thomas Braun Jul 16 '19 at 17:12
  • 1
    Worth mentioning that there are multiple problems in this solution: 1. it only works for 64-bit pointer width targets, one should use `usize` instead of `u64`; 2. one doesn't need `transmute`, you can cast the `usize` value to a raw pointer with `as` and dereference it instead; 3. this creates a reference with n unbounded lifetime, so it can live longer than the original value. See [playground example](https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=6bee25c3e9243d30f93e5f2c9a4b3e57) with suggested changes + UB. – E_net4 Jul 16 '19 at 17:13
  • Very interesting addition Enet. Thanks! – Thomas Braun Jul 16 '19 at 17:41