Topic: Member pointers allow circumventing protected member access
Author: "Bo Persson" <bop@gmb.dk>
Date: Fri, 26 Jun 2009 23:11:40 CST Raw View
litb wrote:
> As it turns out, you can access the protected members of any class
> by taking a member pointer and then applying it to an object of that
> class. The example below seems to be well-formed according to 11.2
> [class.access.base]/5, and to the additional rules of 11.5
> [class.protected]/1, even though there is no object of a derived
> class involved at all.
>
> struct X {
> protected:
> int m;
> };
>
> int& getM(X &x) {
> struct Voyeur : X { using X::m; };
> return x.*(&Voyeur::m);
> }
>
> int main() {
> X x;
> getM(x) = 0;
> }
>
> This can also be achieved by a static member function within the
> derived class.
I don't hink this is 'circumventing' in any way, but by design. By
making the member protected, you grant visibility to any derived
classes, and trust them to behave properly.
If you don't want this effect, you should make the variable private.
Bo Persson
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Lars Tetzlaff <lars.tetzlaff@gmx.net>
Date: Sat, 27 Jun 2009 09:58:15 CST Raw View
Bo Persson schrieb:
> litb wrote:
>> As it turns out, you can access the protected members of any class
>> by taking a member pointer and then applying it to an object of that
>> class.
...
>>
>> This can also be achieved by a static member function within the
>> derived class.
>
> I don't hink this is 'circumventing' in any way, but by design. By
> making the member protected, you grant visibility to any derived
> classes, and trust them to behave properly.
>
> If you don't want this effect, you should make the variable private.
>
>
> Bo Persson
>
>
>
But even if its's private, I can
#define private public
before including the header. Accesscontrol in C++ only is a strong hint
to the user of a class. If someone really want's to access a member it
is possible.
Lars
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Bo Persson" <bop@gmb.dk>
Date: Sat, 27 Jun 2009 18:06:44 CST Raw View
Lars Tetzlaff wrote:
> Bo Persson schrieb:
>> litb wrote:
>>> As it turns out, you can access the protected members of any class
>>> by taking a member pointer and then applying it to an object of
>>> that class.
>
> ...
>
>>>
>>> This can also be achieved by a static member function within the
>>> derived class.
>>
>> I don't hink this is 'circumventing' in any way, but by design. By
>> making the member protected, you grant visibility to any derived
>> classes, and trust them to behave properly.
>>
>> If you don't want this effect, you should make the variable
>> private.
>>
>>
>> Bo Persson
>>
>>
>>
>
> But even if its's private, I can
>
> #define private public
>
> before including the header. Accesscontrol in C++ only is a strong
> hint to the user of a class. If someone really want's to access a
> member it is possible.
>
In theory this make the program invalid, as #defining keywords is
explicitly forbidded (17.4.3.1.1). In practice, it probably would
work.
The C++ access control protects you against accidents, not against a
determined intruder. For example, most objects can be memcpy'd to an
array of unsigned char, giving you access to the underlying bytes. The
result isn't very portable though. :-)
Bo Persson
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Francis Glassborow <francis.glassborow@btinternet.com>
Date: Sun, 28 Jun 2009 17:39:11 CST Raw View
Bo Persson wrote:
>
> The C++ access control protects you against accidents, not against a
> determined intruder. For example, most objects can be memcpy'd to an
> array of unsigned char, giving you access to the underlying bytes. The
> result isn't very portable though. :-)
>
>
Actually most C++ objects of class type cannot be memcpy'ed only those
that are PODs are guaranteed to behave correctly when abused this way.
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Alf P. Steinbach" <alfps@start.no>
Date: Sun, 28 Jun 2009 17:40:50 CST Raw View
* Bo Persson:
> litb wrote:
>> As it turns out, you can access the protected members of any class
>> by taking a member pointer and then applying it to an object of that
>> class. The example below seems to be well-formed according to 11.2
>> [class.access.base]/5, and to the additional rules of 11.5
>> [class.protected]/1, even though there is no object of a derived
>> class involved at all.
>>
>> struct X {
>> protected:
>> int m;
>> };
>>
>> int& getM(X &x) {
>> struct Voyeur : X { using X::m; };
>> return x.*(&Voyeur::m);
>> }
>>
>> int main() {
>> X x;
>> getM(x) = 0;
>> }
>>
>> This can also be achieved by a static member function within the
>> derived class.
>
> I don't hink this is 'circumventing' in any way, but by design. By
> making the member protected, you grant visibility to any derived
> classes, and trust them to behave properly.
Consider what's *not* allowed by the current rules:
class X
{
protected:
int m;
};
class Y: public X
{
static void foo( X const& x )
{
x.m; // !Not permitted.
}
};
If the above was permitted then you could very easily access any class'
inherited protected members simply by deriving a class from the same base class.
As I recall this is even a FAQ item in Cline's FAQ Lite (it's sort of basic),
and this very intentional access restriction is what member pointers break.
And the same rationale that disallows the above "should" ideally apply equally
to member pointer rules, but for the reason discussed below it doesn't:
class P
{
protected:
int m;
};
class Q: public P
{
static void foo( P const& x )
{
x.*(&Q::m); // Permitted...
}
};
What goes on here is perhaps not evident at a glance. For it's not the case that
the right hand side of the '.*' is of type 'int Q::*', or is an 'int Q::*'
implicitly converted to 'int P::*', as one might suspect. As a counter-example:
class Q: public P
{
static void foo( P const& x )
{
int Q::* mp = &Q::m;
x.*mp; // !Not permitted.
}
};
But this can be rewritten as
class Q: public P
{
static void foo( P const& x )
{
int P::* mp = &Q::m;
x.*mp; // Permitted...
}
};
And since there is no implicit conversion Q::* to P::* (for member pointers
there's no implicit up-cast, which is opposite of ordinary pointer rules) the
conclusion is that the expression '&Q::m' necessarily is of type 'int P::*'.
In the standard this access-rule-breaking quite unexpected type is specified by
5.3.1/2, even with an example showing exactly that.
And the only reasonable fix IMHO is to make the type of '&Q::m' an 'int Q::*'.
> If you don't want this effect, you should make the [member] private.
No, I'm sorry, that's meaningless: see above.
Cheers & hth.,
- Alf (hoping that by now he's forgiven for that comment about this in clc++m?,
http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/ec22da1497adbf96)
--
Due to hosting requirements I need visits to <url: http://alfps.izfree.com/>.
No ads, and there is some C++ stuff! :-) Just going there is good. Linking
to it is even better! Thanks in advance!
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]