Question

If I've a class like this,

class Sample
{
private:
      int X;
};

Then we cannot access X from outside, so this is illegal,

    Sample s;
    s.X = 10; // error - private access

But we can make it accessible without editing the class! All we need to do is this,

#define private public  //note this define!

class Sample
{
private:
      int X;
};

//outside code
Sample s;
s.X = 10; //no error!

Working code at ideone : http://www.ideone.com/FaGpZ

That means, we can change the access-specifiers by defining such macros just before the class definition, or before #include <headerfile.h>,

#define public private //make public private
//or
#define protected private //make protected private
//or
#define so on

Isn't it a problem with C++ (Macros/access-specifiers/whatever)?

Anyway, the point of this topic is:

Using macros, we can easily violate encapsulation. Access-specifiers are not foolproof! Am I right?

Was it helpful?

Solution

But we can make it accessible without editing the class! All we need to do is this,

Technically, all you've shown is that "we can turn a legal program into Undefined Behavior" without editing one specific class.

That's hardly news. You can also turn it into undefined behavior just by adding a line such as this to the end of main():

int i = 0;
i = ++i;

Access specifiers in C++ are not a security feature They do not safeguard against hacking attempts, and they do not safeguard against people willfully trying to introduce bugs into you code.

They simply allow the compiler to help you maintain certain class invariants. They allow the compiler to inform you if you accidentally try to access a private member as if it were public. All you've shown is that "if I specifically try to break my program, I can". That, hopefully, should be a surprise to absolutely no one.

As @Gman said, redefining keywords in the C++ language is undefined behavior. It may seem to work on your compiler, but it is no longer a well-defined C++ program, and the compiler could in principle do anything it likes.

OTHER TIPS

First of all, it's illegal to do that. private is a keyword, and you can't use it as an identifier in a macro; your program would be ill-formed.

But in any case, it's not a problem with macro's at all. It's with the fool who used them in a silly manner. :) (They're there to help you be safe, they're not there to help you be safe and block all access to them no matter what you try. C++ protects against Murphy, not Machiavelli.)

Note that you can access privates in a well-formed and well-defined manner, as demonstrated here. Again, this isn't a problem with the language, it's just not the job of the language to do more than necessary to keep prying hands out.

But we can make it accessible without editing the class

Not without editing the source file containing the class though.

Yes, macros let you shoot yourself in the foot. This is hardly news... but this is a particularly non-troubling example of it, as to "violate encapsulation" you have to force the class to either define the bone-headed macro itself, or include a header file which does so.

To put it another way: can you see this being an issue in real, responsible software development?

@Nawaz, your post is interesting, I never thought of this before. However, I believe the answer to your question is simple: think of C++ (or probably any language) security as a way to organize your code, rather than a police.

Basically, since all the variables are defined in your own code, you should be able to access them ALL, no matter where you define them. So you shouldn't be surprised you found a way to access a private member.

Actually, there is even an easier method to access private variables. Imagine you have a library with this class:

class VerySecure
{
private:
    int WorldMostSecureCode;
};

And let's say I am using your very secure class in my code. I can easily access the private member this way:

VerySecury a;
int *myhacker = (int*)(&a);
int b = (*myhacker);
printf("Here is your supposed world secret: %d :-) \n", b);

How is that?!!

No. it will break havoc with private methods. if the compiler is able to tell that these private methods cannot be accessed elsewhere, then they can be inlined and optimized-out, and they may not appear in the object file, so they will be inaccessible.

Take this as an example. It either works, can't link or can't run the executable depending on the optimization/stripping flags you use and how you compile the thing (ie, you can put the implementation in a shared library or not)

class A {
// i need this one ...
private:
        void stupid_private();
public:
        void unlock(std::string password);
};

implementation file :

#include <iostream>
#include "a.h++"

// uncomment this for more g++ fun
// __attribute__((visibility("hidden")))
void A::stupid_private() {
        std::cout << "let's output something silly." << std::endl;
}
void A::unlock(std::string password) {
        if (password == "jumbo")
                stupid_private();
}

the user file :

#define private public
#include "a.h++"

int main() {
        A a;
        a.stupid_private();
        return 0;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top