Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing private data with reinterpret_cast

This seems to compile and access the private data successfully. Is this well-defined behavior?

#include <iostream>
#include <string>

using std::string;

class foo {
    string private_data = "Hello World";
};

int main()
{
    foo f;
    auto* pprivate_data = reinterpret_cast<string*>(&f);
    std::cout << *pprivate_data << '\n';
}

This question is sort of similar, but I believe it doesn't address my question.

like image 741
Ayxan Haqverdili Avatar asked Jul 27 '20 09:07

Ayxan Haqverdili


People also ask

What is the point of reinterpret_cast?

The reinterpret_cast allows the pointer to be treated as an integral type. The result is then bit-shifted and XORed with itself to produce a unique index (unique to a high degree of probability). The index is then truncated by a standard C-style cast to the return type of the function.

Is reinterpret_cast safe?

The reinterpret_cast operator performs potentially unsafe type casts. It is most often used to cast a pointer to a different pointer type. Casting a pointer to a different pointer and back is usually safe and yields the original value.

Is reinterpret_cast undefined Behaviour?

Although the reinterpret_cast itself might be unspecified behaviour, attempting to access the parameters once you've done the cast is undefined behaviour.

Is reinterpret cast compile time?

None of the casts happen at compile time. You only have the data at runtime, in general.


1 Answers

No, the behavior is undefined. For such a reintepret_cast to have meaning, the two objects must be interconvertible

[basic.compound]

4 Two objects a and b are pointer-interconvertible if:

  • they are the same object, or
  • one is a union object and the other is a non-static data member of that object ([class.union]), or
  • one is a standard-layout class object and the other is the first non-static data member of that object, or, if the object has no non-static data members, any base class subobject of that object ([class.mem]), or
  • there exists an object c such that a and c are pointer-interconvertible, and c and b are pointer-interconvertible.

If two objects are pointer-interconvertible, then they have the same address, and it is possible to obtain a pointer to one from a pointer to the other via a reinterpret_­cast. [ Note: An array object and its first element are not pointer-interconvertible, even though they have the same address. — end note ]

The only bullet that might apply is the one about standard layout classes. If we consult that definition, we see

[class.prop]

3 A class S is a standard-layout class if it:

  • has no non-static data members of type non-standard-layout class (or array of such types) or reference,
  • [...]

there is an immediate problem. Any non-static data members of the object must be standard layout themselves. There is no guarantee std::string is a standard layout type. So the behavior is undefined.

like image 119
StoryTeller - Unslander Monica Avatar answered Sep 21 '22 17:09

StoryTeller - Unslander Monica