打败C ++访问资格的最简洁方法是什么?

时间:2010-09-29 11:20:41

标签: c++ private

我决定通过访问内部变量解决GNU libstdc ++中的错误。回想一下Johannes在他的博客上解决了这个问题,我检查了一下......但除了获得静态初始化程序来执行脏工作的基本概念之外,无法理解代码。所以,我把它归结为这个,这非常紧凑。

但是,正如所评论的那样,这会导致每个翻译单元重复的对象和访问器功能很少,从而导致令人讨厌的级联。 Boost最佳实践是否有规范的方法可以做到这一点?

为不好的幽默道歉,但这不是无偿的......我们不希望这段代码“安全工作”!

/* This hack installs a static initializer, so to avoid the ordering fiasco,
make one fresh copy per translation unit, via anonymous namespace. */
namespace {

template< typename T, T value, T &dest >
struct class_rape {
    class_rape() { dest = value; } // you've been raped in the class!
    static class_rape r;
};
template< typename T, T value, T &dest >
class_rape< T, value, dest > class_rape< T, value, dest >::r;


// Usage (cvt_[w]filebuf is a specialization of GCC basic_filebuf)

typedef bool cvt_filebuf::*cvt_fb_reading_t;
typedef bool cvt_wfilebuf::*cvt_wfb_reading_t;

/* Access these variables, or functions accessing them (applies recursively),
only in anonymous namespace or in non-header file, per one-definition rule. */
cvt_fb_reading_t cvt_filebuf_reading;
cvt_wfb_reading_t cvt_wfilebuf_reading;

template struct class_rape
    < cvt_fb_reading_t, &cvt_filebuf::_M_reading, cvt_filebuf_reading >;
template struct class_rape
    < cvt_wfb_reading_t, &cvt_wfilebuf::_M_reading, cvt_wfilebuf_reading >;

}

顺便说一句,这是上下文:http://pastie.org/1188625

更新

我在下面的答案中解决了重复问题。因此,现在我对一个确定性的,定义明确的解决方案感兴趣,该解决方案不涉及编辑任何目标代码,并允许一次攻击模板的多个特化。 (给定的hack需要为每个目标模板专门化进行新的实例化。)

3 个答案:

答案 0 :(得分:3)

非法访问:

class ClassIWantToViolate
{
    // Internal State
    public:
        template<typename T> void violate() {} // Do nothing
};

然后在你的代码中你可以违反这个类:

namespace { struct Attack {}; }

template<>
void ClassIWantToViolate::violate<Attack>()
{
     // Access to internal state here.

     // This is your own version of violate based on a local specialization
     // Thus it is unique but still has access to internal state of the class.
}

答案 1 :(得分:0)

我可能会采用一种不那么聪明的方法。从外部访问班级的私人成员是一件罕见的事情,或者至少对我来说(从未做过)。在我的实施中,我能够在几分钟内完成这个......

  • 将fstream复制到我称为evil_fstream.h的本地项目文件
  • 将evil_fstream.h中的命名空间从std更改为evil
  • 从evil_fstream.h中删除私有受保护:的所有实例

然后这段代码编译:

#include <fstream>
#include "evil_fstream.h"

using namespace std;

typedef evil::basic_filebuf<char, char_traits<char> > evil_filebuf_t;

int main() {

   std::basic_filebuf<char, char_traits<char> > fb;

   evil_filebuf_t* efb = (evil_filebuf_t*)&fb;

   efb->_Pcvt; // access a private member

   return 1;
}

答案 2 :(得分:0)

呸,我发布这篇文章已经太晚了......我应该睡觉了。

我可以通过使变量真正全局化来避免静态初始化顺序失败和重复问题,并且只是多次初始化它们。由于初始化值每次都相同,因此它们何时发生并不重要。第一次初始化发生在第一次访问之前,因为初始化首先出现在可能发生访问的每个转换单元中。

typedef bool cvt_filebuf::*cvt_fb_reading_t;
typedef bool cvt_wfilebuf::*cvt_wfb_reading_t;

/* Place accessible variables in global, non-anonymous namespace. */
cvt_fb_reading_t cvt_filebuf_reading;
cvt_wfb_reading_t cvt_wfilebuf_reading;

/* This hack installs a static initializer, so to avoid the ordering fiasco,
make one fresh copy per translation unit, via anonymous namespace. */
namespace {

template< typename T, T value, T &dest >
class class_rape { // change access qualification of hack to guarantee ODR, LOL
    class_rape() { dest = value; } // you've been raped in the class!
    static class_rape r;
};
template< typename T, T value, T &dest >
class_rape< T, value, dest > class_rape< T, value, dest >::r;

template struct class_rape
    < cvt_fb_reading_t, &cvt_filebuf::_M_reading, cvt_filebuf_reading >;
template struct class_rape
    < cvt_wfb_reading_t, &cvt_wfilebuf::_M_reading, cvt_wfilebuf_reading >;

}

/* Accessor functions go here, also outside anonymous namespace. */