A hack to circumvent access - how bad?

Discussion in 'C++' started by Victor Bazarov, Sep 23, 2009.

  1. Hello,

    Please consider the code below. The 'BS/CS/DS' class hierarchy lives in
    a third-party library that I can't change. It's broken (a little) in
    the sense that I need to call a protected member function of 'BS' from
    outside of the hierarchy. The 'A/AA/AAA' is my own hierarchy.

    To gain access to 'BS::foo' from 'A::bar', I perform a dirty hack (see
    the static_cast). The only hope is that since 'HackBS' contains no data
    members of its own, it won't disturb the hierarchy (memory layout, etc).

    Oh, there are, of course other members in 'BS' that do not represent an
    access problem...

    Another thing: we aren't supposed to use virtual or multiple inheritance
    for this project.

    So, give it to me straight: is this hack a disaster waiting to happen?
    So far it "worked" (produced the desired results), although of course
    the code has UB, AFAIUI.

    --------------------------------------------
    #include <iostream>
    #include <ostream>

    class BS
    {
    char bs;
    public:
    BS(char b) : bs(b) {}
    virtual ~BS() {}
    protected:
    virtual void foo()
    { std::cout << "BS::foo(), bs = " << bs << "\n"; }
    };

    class CS : public BS
    {
    int cs;
    public:
    CS(int c) : BS(c % 10 + '0'), cs(c) {}

    void foo()
    { BS::foo(); std::cout << " CS :: foo(), cs = " << cs << '\n'; }
    };

    class DS : public CS
    {
    double ds;
    public:
    DS(double d) : CS(int(d*100)), ds(d) {}

    protected:
    void foo()
    { CS::foo(); std::cout << " DS :: foo(), ds = " << ds << "\n"; }
    };

    class HackBS : public BS
    {
    friend class A;
    public:
    HackBS() : BS(0) {}
    };

    class A
    {
    BS* pBS;
    public:
    void setBS(BS* p) { pBS = p; }
    void bar() { static_cast<HackBS*>(pBS)->foo(); }
    };

    class AA : public A
    {
    };

    class AAA : public AA
    {
    };

    int main()
    {
    A a;
    a.setBS(new BS('z'));
    a.bar();

    AA aa;
    aa.setBS(new CS(42));
    aa.bar();

    AAA aaa;
    aaa.setBS(new DS(3.14159));
    aaa.bar();
    }
    --------------------------------------------

    Thanks!

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Sep 23, 2009
    #1
    1. Advertising

  2. Victor Bazarov wrote:
    > Hello,
    >
    > Please consider the code below. The 'BS/CS/DS' class hierarchy lives in
    > a third-party library that I can't change. It's broken (a little) in
    > the sense that I need to call a protected member function of 'BS' from
    > outside of the hierarchy. The 'A/AA/AAA' is my own hierarchy.
    >


    Sounds wrong that you have to call a protected member function. I don't
    know details, but are you sure there isn't another way to do what you want?

    > To gain access to 'BS::foo' from 'A::bar', I perform a dirty hack (see
    > the static_cast). The only hope is that since 'HackBS' contains no data
    > members of its own, it won't disturb the hierarchy (memory layout, etc).
    >
    > Oh, there are, of course other members in 'BS' that do not represent an
    > access problem...
    >
    > Another thing: we aren't supposed to use virtual or multiple inheritance
    > for this project.
    >
    > So, give it to me straight: is this hack a disaster waiting to happen?
    > So far it "worked" (produced the desired results), although of course
    > the code has UB, AFAIUI.


    Isn't any UB a disaster waiting to happen?


    < code cut >
    Vladimir Jovic, Sep 23, 2009
    #2
    1. Advertising

  3. Victor Bazarov <> writes:

    > Please consider the code below. The 'BS/CS/DS' class hierarchy lives
    > in a third-party library that I can't change. It's broken (a little)
    > in the sense that I need to call a protected member function of 'BS'
    > from outside of the hierarchy. The 'A/AA/AAA' is my own hierarchy.


    Protected methods are meant to be used by subclasses.

    class YourClass: public DS {
    public:
    void doSomethingNasty(){
    this->foo(); // call the protected method
    }
    };

    --
    __Pascal Bourguignon__
    Pascal J. Bourguignon, Sep 23, 2009
    #3
  4. Victor Bazarov

    Balog Pal Guest

    "Victor Bazarov" <>

    > Please consider the code below. The 'BS/CS/DS' class hierarchy lives in a
    > third-party library that I can't change. It's broken (a little) in the
    > sense that I need to call a protected member function of 'BS' from outside
    > of the hierarchy. The 'A/AA/AAA' is my own hierarchy.
    >
    > To gain access to 'BS::foo' from 'A::bar', I perform a dirty hack (see the
    > static_cast). The only hope is that since 'HackBS' contains no data
    > members of its own, it won't disturb the hierarchy (memory layout, etc).


    I used similar things to extend/fix MFC classes with nonvirtual member
    functions. Sometimes to smuggle out an incorrectly overprotected member too.
    And where dealing with "original" instances used simply upcast. Can't recall
    a single problem related.

    If I wanted to strenghten it, I'd use some assert (possibly static) that
    verify the derived class's size is the same and the pointer after the cast
    is also the same.
    Balog Pal, Sep 23, 2009
    #4
  5. Victor Bazarov wrote:

    > Please consider the code below. The 'BS/CS/DS' class hierarchy lives in
    > a third-party library that I can't change. It's broken (a little) in
    > the sense that I need to call a protected member function of 'BS' from
    > outside of the hierarchy. The 'A/AA/AAA' is my own hierarchy.
    >
    > To gain access to 'BS::foo' from 'A::bar', I perform a dirty hack (see
    > the static_cast). The only hope is that since 'HackBS' contains no data
    > members of its own, it won't disturb the hierarchy (memory layout, etc).


    []

    AFAIK, access specifiers (i.e. private, protected, public) do not affect memory
    layout, neither there is a difference in memory layout between class and struct.

    Therefore, before including that third-party header just do:

    #define class struct
    #define private public
    #define protected public


    And that would effectively disable all member access restrictions.

    --
    Max
    Maxim Yegorushkin, Sep 23, 2009
    #5
  6. Victor Bazarov

    Jerry Coffin Guest

    In article <4aba508f$0$9753$>,
    says...

    [ ... ]

    > AFAIK, access specifiers (i.e. private, protected, public) do not
    > affect memory layout, neither there is a difference in memory
    > layout between class and struct.


    Specifiers can (at least theoretically) affect memory layout -- see:

    http://groups.google.com/group/comp.lang.c .moderated/browse_frm/thr
    ead/1f21a3731a645cab/3f68c6bedded3ce5

    for a discussion that covers most of the gory details.

    Realistically, however, I'd guess you're right with most compilers
    most of the time though.

    --
    Later,
    Jerry.
    Jerry Coffin, Sep 23, 2009
    #6
  7. On 23 Set, 18:44, Maxim Yegorushkin <>
    wrote:
    > Victor Bazarov wrote:
    > > Please consider the code below.  The 'BS/CS/DS' class hierarchy lives in
    > > a third-party library that I can't change.  It's broken (a little) in
    > > the sense that I need to call a protected member function of 'BS' from
    > > outside of the hierarchy.  The 'A/AA/AAA' is my own hierarchy.

    >
    > > To gain access to 'BS::foo' from 'A::bar', I perform a dirty hack (see
    > > the static_cast).  The only hope is that since 'HackBS' contains no data
    > > members of its own, it won't disturb the hierarchy (memory layout, etc)..

    >
    > []
    >
    > AFAIK, access specifiers (i.e. private, protected, public) do not affect memory
    > layout, neither there is a difference in memory layout between class and struct.
    >
    > Therefore, before including that third-party header just do:
    >
    >      #define class struct
    >      #define private public
    >      #define protected public
    >
    > And that would effectively disable all member access restrictions.


    I think you could get problems with the first macro if the header
    defines some template which use the "class" keyword instead of the
    "typename" one. In such a case, the header will fail to compile.

    Just my two cents.

    Cheers,
    Francesco
    --
    Francesco S. Carta, hobbyist
    http://fscode.altervista.org
    Francesco S. Carta, Sep 23, 2009
    #7
  8. Victor Bazarov

    Balog Pal Guest

    "Jerry Coffin" <>
    >> AFAIK, access specifiers (i.e. private, protected, public) do not
    >> affect memory layout, neither there is a difference in memory
    >> layout between class and struct.

    >
    > Specifiers can (at least theoretically) affect memory layout -- see:


    I hoped they do in practice. Th current layout rules leave pretty much
    chance to waste space, that can be reduced.

    > http://groups.google.com/group/comp.lang.c .moderated/browse_frm/thr
    > ead/1f21a3731a645cab/3f68c6bedded3ce5
    >
    > for a discussion that covers most of the gory details.
    >
    > Realistically, however, I'd guess you're right with most compilers
    > most of the time though.


    I would not go with such a drastic solution if I have the 3rd party stuff as
    binary+headers, only if there is an ability to compile the library too with
    the modifications. (fat chance...)

    However, if the pain is only the access right, there's a lighter hack.
    Instead of replacing private to public, inserting a line saying

    friend struct MyHack;

    If the files are allowed to edit, it is an easy insert, and TMK breaks only
    theoretic rules. With a little luck it can be piggybacked on keyword
    private, or some other text that is known to be in the header via #define.

    Like

    #define private friend struct MyHack; private

    or the same with protected, is worth a try -- certainly it fails if the
    keyword is used in the base class list. What really adds to the problem if
    the target .h file includes other headers -- though if they use include
    guards it may be worked around by pre-inclusion.


    >
    > --
    > Later,
    > Jerry.
    Balog Pal, Sep 23, 2009
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    0
    Views:
    851
  2. Eric Anderson

    Bad Transform or Bad Engine?

    Eric Anderson, Oct 4, 2005, in forum: XML
    Replies:
    1
    Views:
    364
    Peter Flynn
    Oct 5, 2005
  3. Do Re Mi chel La Si Do

    To circumvent the bug cp1252

    Do Re Mi chel La Si Do, May 15, 2005, in forum: Python
    Replies:
    0
    Views:
    424
    Do Re Mi chel La Si Do
    May 15, 2005
  4. Just Another Victim of the Ambient Morality

    Bad hack fix around a bizarre problem...

    Just Another Victim of the Ambient Morality, Jan 11, 2009, in forum: Python
    Replies:
    1
    Views:
    1,535
    Diez B. Roggisch
    Jan 11, 2009
  5. rantingrick
    Replies:
    44
    Views:
    1,175
    Peter Pearson
    Jul 13, 2010
Loading...

Share This Page