So, always thought that it's impossible without undefined behavior to access private members of arbitrary classes without being friend.
Today I noticed I've been horribly wrong, after reading some insightful commit to the clang compiler, that enabled it to allow explicit instantiation to disregard accessibilities, as per the Standard. This enables us to access private members of others. As an experiment, I created some class templates
template<typename Tag> struct result { /* export it ... */ typedef typename Tag::type type; static type ptr; }; template<typename Tag> typename result<Tag>::type result<Tag>::ptr; template<typename Tag, typename Tag::type p> struct rob : result<Tag> { /* fill it ... */ struct filler { filler() { result<Tag>::ptr = p; } }; static filler filler_obj; }; template<typename Tag, typename Tag::type p> typename rob<Tag, p>::filler rob<Tag, p>::filler_obj;
So, how is it used? Let's have an example
struct A { private: void f() { std::cout << "proof!" << std::endl; } }; struct Af { typedef void(A::*type)(); }; template class rob<Af, &A::f>;
Ah, that's all to expose poor A's "f" member. Now anyone can use them using the member pointer snytax, as does the main function below
int main() { A a; (a.*result<Af>::ptr)(); }
Of course, as Herb Sutter told us, don't do these things in real code.
19 comments:
Cute hack :-)
I recently started to think whether enforcing privateness is really a good thing. It can be useful to have access to private variables if you are debugging with printf statements. Or when you are dealing with badly designed legacy code. If we can have a const_cast, then why not a "private_cast"?
Can you give the corresponding revision number of clang ?
I think you're forgetting that C++ is not an object-oriented language. It is a language that supports many object-oriented idioms.
I can think of several ways of accessing a private method in C++. Off the top of my head:
- Function Pointers
- Friend classes / functions.
- static member functions.
- copy constructors / assignment operators (allow access to private members of rhs if it's the same type).
- Just make it public(!)
I always view privacy as something to help other programmers. If something is private, I'm saying to any other programmer 'please don't interfere with this stuff when using this class'.
Of course they can still change it if they want to, but they have to consciously make that decision which means they will more likely be aware of the consequences of doing so.
i like to use #define private public and #define protected public
Guys, Herb Sutter says "This isn't actually a problem. The issue here is of protecting against Murphy vs. protecting against Machiavelli... that is, protecting against accidental misuse (which the language does very well) vs. protecting against deliberate abuse (which is effectively impossible). In the end, if a programmer wants badly enough to subvert the system, he'll find a way, as demonstrated above in Examples 1 to 3.". You do *not* want to do this at home. You also do want to notice: This blog demonstrates a way that your compiler will have to support in order to be a C++ compiler. Any #define hacks and the-like are not guaranteed to work.
Wow. Any chance of posting a follow-up to explain a little more what is going on? Does the function pointer declaration typedef void(A::*type)() need to match the private method you are trying to access?
Applying this method to virtual functions one may only call final overriding method of the object's type, ancestor methods are not accessible.
E.g.:
struct A {
private:
virtual void f() {
std::cout << "proof!" << std::endl;
}
};
struct B: public A {
private:
virtual void f() {
std::cout << "not proof!" << std::endl;
}
};
struct Af { typedef void(A::*type)(); };
template class rob;
int main() {
B a;
(a.*result::ptr)();
}
would print "not proof!" (B::f), although we'd like to see "proof!" (A::f).
sorry, but I got a compile error
VS 2008
: error C2248: 'A::f' : cannot access private member declared in class 'A'
Spending some time cleaning this up and simplifying it... it looks like derivation of rob from result is superfluous.
Having analyzed and rewritten the code it turns out I ended up very close to where you started! Here's my version including explanatory comments: https://gist.github.com/1528856
very nice. but it won't work if A::f() is overloaded.
well, I have to swallow my own words -- it actually works even with overloaded functions, if you use the RIGHT compiler :) GCC handles it well, whereas MSVC complains about not being able to access private member...
Thank you for the solution! private QCheckListItem::setState(int,bool,bool) in Qt3 has the complexity > O^2 when the checkbox parent is the checkbox controller when legally called
Nice ...
And ideas how this could be extended to also access private _static_ members?
Found out how to do it with static members myself:
struct A {
private:
static void f() {
std::cout << "proof!" << std::endl;
}
};
struct Af { typedef void(*type)(); };
template class rob;
int main() {
A a;
(*result::ptr)();
}
Embarrassingly easy way to make money…
OMG.
I face palmed when I saw how easy it was for people to make money online using this method.
[Click here for the embarrassingly easy way to make money]
If you can’t do this…
Then I don’t know what to say.
Check it out. https://30daysuccess.club?23354
I get segfaults with gcc and clang (https://wandbox.org/permlink/CWeIkBwi95eSpLPK). Clang spits out a couple of warnings in addition.
Am I missing something how to get this working?
Yes, in real code we just cast to void* and access the VTable index manually. It's also easier to understand what's happening.
Post a Comment