指向成员的指针可能绕过成员的访问级别

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

本文关键字:成员 访问级别 指针      更新时间:2023-10-16

我们臭名昭著的litb有一篇关于如何规避访问检查的有趣文章。

这个简单的代码充分证明了这一点:

#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;
}

它使用gcc 4.3.4、gcc 4.5.1、gcc 4.7.0编译和运行(输出42)(请参阅用户1131467的评论),并在C++03严格模式和MSVC 2005中使用Clang 3.0和Comeau C/C++4.3.10.1编译。

Luchian问我这个答案,我用它来证明它实际上是合法的。我同意Luchian的观点,认为这很奇怪,但Clang和Comeau都是可用的大多数"标准"编译器的有力竞争者(默认情况下比MSVC更重要)。。。

我在我现有的标准草案中找不到任何东西(n3337是我拿到的最后一个版本)。

所以。。。有人真的能证明它是否合法吗?

是的,这是合法的。相关文本见§14.7.2/12,讨论了显式模板实例化:

12通常的访问检查规则不适用于用于指定显式实例化的名称。[注意:特别是,函数声明符中使用的模板参数和名称(包括参数类型、返回类型和异常规范)可能是通常不可访问的私有类型或对象,模板可能是通常不会访问的成员模板或成员函数可访问。--尾注]

埃姆帕西斯矿。

该代码显然是非法的(并且需要编译时诊断)。行中:

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

表达式CCD_ 2访问CCD_。

标准对此非常明确:;应用访问控制统一到所有名称,无论这些名称是从声明或表达式“(§11/4,增加了重点)。由于aA中是私有名称,因此在A之外对它的任何引用都是非法的。