Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

May pointer to members circumvent the access level of a member?

Our infamous litb has an interesting article on how to circumvent the access check.

It is fully demonstrated by this simple code:

#include <iostream>

template<typename Tag, typename Tag::type M>
struct Rob { 
  friend typename Tag::type get(Tag) {
    return M;
  }
};

// use
struct A {
  A(int a):a(a) { }
private:
  int a;
};

// tag used to access A::a
struct A_f { 
  typedef int A::*type;
  friend type get(A_f);
};

template struct Rob<A_f, &A::a>;

int main() {
  A a(42);
  std::cout << "proof: " << a.*get(A_f()) << std::endl;
}

Which compiles and runs (output 42) with gcc 4.3.4, gcc 4.5.1, gcc 4.7.0 (see user1131467's comment) and compiles with Clang 3.0 and Comeau C/C++ 4.3.10.1 in C++03 strict mode and MSVC 2005.

I was asked by Luchian on this answer in which I used it to justify that it was actually legal. I agree with Luchian that it is weird, however both Clang and Comeau are close contenders for the most "Standard" compilers available (much more so than MSVC by default)...

And I could not find anything in the drafts of the Standards I have available (n3337 being the last version I got my hands on).

So... can anyone actually justifies that it is legal or not ?

like image 816
Matthieu M. Avatar asked Mar 28 '12 12:03

Matthieu M.


2 Answers

Yes, it's legal. The relevant text is at §14.7.2/12, talking about explicit template instantiation:

12 The usual access checking rules do not apply to names used to specify explicit instantiations. [ Note: In particular, the template arguments and names used in the function declarator (including parameter types, return types and exception specifications) may be private types or objects which would normally not be accessible and the template may be a member template or member function which would not normally be accessible. — end note ]

Emhpasis mine.

like image 168
GManNickG Avatar answered Nov 11 '22 23:11

GManNickG


The code is clearly illegal (and requires a compile time diagnostic). In the line:

template struct Rob<A_f, &A::a>;

the expression A::a accesses a private member of A.

The standard is very clear about this: “Access control is applied uniformly to all names, whether the names are referred to from declarations or expressions.“ (§11/4, emphasis added). Since a is a private name in A, any reference to it outside of A is illegal.

like image 33
James Kanze Avatar answered Nov 11 '22 21:11

James Kanze