Может ли указатель на участников обойти уровень доступа участника? - PullRequest
13 голосов
/ 28 марта 2012

У нашей печально известной газеты есть интересная статья о , как обойти проверку доступа .

Это полностью демонстрируется этим простым кодом:

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

, который компилируется и запускается (вывод 42) с gcc 4.3.4 , gcc 4.5.1 , gcc 4.7.0 (см. Комментарий пользователя 1131467) и компилируется с Clang 3.0 и Comeau C / C ++ 4.3.10.1 в строгом режиме C ++ 03 и MSVC 2005.

Лучиан спросил меня об этом этом ответе , в котором я использовал его, чтобы обосновать, что это действительно законно. Я согласен с Лучианом в том, что это странно, однако и Clang, и Comeau являются близкими претендентами на большинство доступных «стандартных» компиляторов (намного больше, чем MSVC по умолчанию) ...

И я не смог найти ничего в черновиках Стандартов, которые у меня есть (n3337 - последняя версия, в которую я попал).

Итак ... может ли кто-нибудь на самом деле оправдать, что это законно или нет ?

Ответы [ 2 ]

13 голосов
/ 28 марта 2012

Да, это законно . Соответствующий текст в §14.7.2 / 12 говорит о явной реализации шаблона:

12 Обычные правила проверки доступа не применяются к именам, используемым для указания явных экземпляров . [ Примечание : В частности, аргументы и имена шаблонов, используемые в деклараторе функции (включая типы параметров, типы возвращаемых данных и спецификации исключений), могут быть закрытыми типами или объектами, которые обычно недоступны, и шаблон может быть шаблон члена или функция-член, которая обычно не доступны. - Конечная нота ]

Эхпасис мой.

5 голосов
/ 28 марта 2012

Код явно недопустим (и требует диагностики времени компиляции).В строке:

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

выражение A::a обращается к закрытому члену A.

. Стандарт очень четко говорит об этом: «Контроль доступа применяется равномерно к все имен, упоминаются ли имена из объявлений или выражений. «(§11 / 4, выделение добавлено).Поскольку a является частным именем в A, любая ссылка на него вне A является недопустимой.

...