Sign in to follow this  
Alundra

Do you use friend to avoid security problems ?

Recommended Posts

fastcall22    10846

Do you use friend to avoid security problems of public functions ?

There isn't any inherit security problems with the use of public functions...

The friend keywords helps enforce class invariants.

Share this post


Link to post
Share on other sites
Alundra    2316

For example a public function "Notify" called by all class managed by this class when something change.

The user of the API should not have access to this function, but it's needed to be public to be called.

But it's not a security problem here.

 

Security problem could be a function which change a private array, only needed by class managed by the class which contains this function.

Since it's public, it can be called by the user of the API, which can cause problem.

Edited by Alundra

Share this post


Link to post
Share on other sites
frob    44974

For example a public function "Notify" called by all class managed by this class when something change.

 

I don't follow.

 

Those needing to be notified can register a callback function. A public add/remove pair can handle any system wanting notifications.

 

If the object needs to be notified, expose a function that triggers a refresh or update.

 

Notification in either direction does not require access to private members.  Both can be part of the public interface.

Share this post


Link to post
Share on other sites
Agony    3452

For example a public function "Notify" called by all class managed by this class when something change.

The user of the API should not have access to this function, but it's needed to be public to be called.

But it's not a security problem here.

 

Security problem could be a function which change a private array, only needed by class managed by the class which contains this function.

Since it's public, it can be called by the user of the API, which can cause problem.

 

If you're truly concerned with security, that is, you want to prevent malicious users of your API from doing things that could be harmful to other users or to you, then making functions private will do very little to help you achieve your goals of protection.  If a malicious person wants to call a private function, they only need to discover its existence, find its location in the executable, determine the proper calling convention and parameters, and then they can freely call it with whatever parameter values they want.  While the above steps aren't trivial, especially for your average script kiddie, for a well practiced malicious agent it's not that hard.

 

If on the other hand you want to protect an innocent user from naively doing things that might accidentally cause them or others hard, then yes, friend can sometimes be a tool to help you achieve this goal, although it is debatable if it often or ever the most appropriate tool.  I don't have a strong opinion personally, except that when I do use it, I take extra care to ensure that it is justified, and that I'm not overlooking a better solution due to lack of imagination or experience.  I'll use it more freely in prototypes because the code tends to be throw-away.  In more long-lived code, or when refactoring code that I thought was going to be throw-away but apparently is outliving its expected lifespan, I am biased against it.

 

Note that when Microsoft designed C#, they thought that this usage was valuable and justifiable enough that they added the "internal" keyword which is even more blunt than C++'s "friend" keyword.  Though I suspect there's just as much debate over this language feature as exists for "friend".

 

I personally suspect that there's always a better tool, a better design or architecture available for providing a convenient, safe, and efficient API without resorting to the use of "friend".  However, sometimes the cost of finding that alternative design and implementing it might be higher than the cost of just taking the easy route and using "friend".  It's up the the wisdom and experience of the decision-making engineer to distinguish between those cases.

Share this post


Link to post
Share on other sites
frob    44974

I suppose the original poster might be thinking "security" as in "network security", even though that has nothing to do with C++, maybe more like a SOAP or REST interface.

 

 

In that type of scenario when you are concerned about authorized sources, any exposed method can also require an authentication token. Discard unauthorized or unauthenticated commands, either silently or with an appropriate error, based on your usage needs.  

 

As an example, the APIs for point of sale terminals and credit card readers are publicly available and widespread. The public API for transferring funds through banks, through credit card systems, through PayPal, through other systems can all be found with a few seconds of searching.  Even though the details are public they require proper authentication before any transactions are completed.  

 

Public availability does not mean insecure.

Edited by frob

Share this post


Link to post
Share on other sites
Matias Goldberg    9582
There is a misconception among beginner programmers that the keywords 'private' and 'protected' from C++ give you higher security.
It doesn't.

Those keywords are there to guide other programmers into what the original author intended (e.g. "you're not supposed to modify this variable directly", "if you need to read this variable, then the approach you're doing right now is incorrect and will be inefficient or turn into spaghetti very soon") and not as a means of protecting data in RAM from hackers. Edited by Matias Goldberg

Share this post


Link to post
Share on other sites
ericrrichards22    2434

I had forgotten the details of what friend in C++ does...  Working in .Net land most of the time, I can't remember really needing it.

 

The only time that I remember ever creating friend functions was for C++ ostream stuff.  In .Net, you would just override ToString() in most cases instead, however.

 

C#'s internal is a somewhat different beast.  In a nutshell, it is coarser, and basically means public, but only within assembly boundaries*.  In that case, it can be useful if you want to hide your implementations to external consumers of your library, and force users to go through your publicly exposed interfaces.  Or if you have some utility code that shouldn't be exposed.  Of course with reflection, you can always get at things if you try hard enough.

 

Unit-testing gets to be a pain, though.  I'm not real excited about having to mark what could be private, static, pure helpers as internal in order to be able to write tests in a test assembly.  Although that pain is often an indication that there are refactorings that should be made.

 

* there's the whole InternalsVisibleTo mess,which lets you whitelist certain defined assemblies to poke at your internal bits.

Share this post


Link to post
Share on other sites
Promit    13246

I honestly think private/protected are worthless features in C++. They serve some purpose in module-based languages like Java or C#, but their basic use in C++ is just not particularly compelling.

Share this post


Link to post
Share on other sites
SmkViper    5396

I honestly think private/protected are worthless features in C++. They serve some purpose in module-based languages like Java or C#, but their basic use in C++ is just not particularly compelling.


Private is very important in that it lets you provide a clean API to end users that allow you to modify the internals with minimal recompilation and preserve class invariants. Protected has a few useful applications (for holding an interface's destructor for example if you don't want someone destroying an object via the interface).

Like others have said, access semantics, like other things in the language, are there to protect the programmer from making mistakes and to help enforce good code design, not to actually make your code secure from attacks. The CPU of course does not see these access semantics.

Share this post


Link to post
Share on other sites
Alundra    2316

The primary goal of the post is to secure the end user of the API but the part about attacks was not bad.

EDIT because of language mistakes :

The primary goal of the post is about security for the end user of the API but the part about attacks was not bad.

Edited by Alundra

Share this post


Link to post
Share on other sites
Promit    13246

Private is very important in that it lets you provide a clean API to end users that allow you to modify the internals with minimal recompilation and preserve class invariants. Protected has a few useful applications (for holding an interface's destructor for example if you don't want someone destroying an object via the interface).

Except we're talking about C++, which immediately and catastrophically fucks this up by making the private internals part of the header anyway. So then we end up with tricks ranging from vanilla polymorphic interfaces to pImpl idiom variations, rendering the whole exercise pointless.


Like others have said, access semantics, like other things in the language, are there to protect the programmer from making mistakes and to help enforce good code design

And the moment you inflict friend, we're not talking about good code design anymore, we're talking about continuing hacks where the core design has already gone awry. It's worth noting that a number of modern languages get by just fine without access semantics. My argument is they may get along better without them and that the very use of access semantics represents total failure of encapsulation in C++. Why? Because even if I can't access the internal details of a class, I can see them just fine due to other encapsulation-puncturing issues in the language. That serves to bind clients to implementation details anyway, in the absence of pImpl type techniques. Lacking the relevant semantics forces you to deal with the interface/implementation divide directly. This is not the case in Java or C#, which implement sane module systems and let you alter implementations without impacting clients.

 

If you consider C++ private/protected semantics relevant to your code design, it's time for a redesign.

Edited by Promit

Share this post


Link to post
Share on other sites
SmkViper    5396

Private is very important in that it lets you provide a clean API to end users that allow you to modify the internals with minimal recompilation and preserve class invariants. Protected has a few useful applications (for holding an interface's destructor for example if you don't want someone destroying an object via the interface).

Except we're talking about C++, which immediately and catastrophically fucks this up by making the private internals part of the header anyway. So then we end up with tricks ranging from vanilla polymorphic interfaces to pImpl idiom variations, rendering the whole exercise pointless.

Pointless? Hardly. Just because you CAN get around something doesn't make it pointless. In most cases, getting around a properly designed interface's boundaries not only causes compiler warnings, but just plain looks wrong.

I mean, as long as you're complaining about implementation in headers, you might as well also complain about templates which force implementation in headers. Or the fact that the compiler sees all your code anyway via link-time code generation and optimizations.

At this point you're not complaining about public/private/protected, you're just complaining about the header and compilation unit system which has long outgrown its usefulness and is being replaced with proper modules in a future C++ version once they nail down the spec.

Like others have said, access semantics, like other things in the language, are there to protect the programmer from making mistakes and to help enforce good code design

And the moment you inflict friend, we're not talking about good code design anymore, we're talking about continuing hacks where the core design has already gone awry. It's worth noting that a number of modern languages get by just fine without access semantics. My argument is they may get along better without them and that the very use of access semantics represents total failure of encapsulation in C++. Why? Because even if I can't access the internal details of a class, I can see them just fine due to other encapsulation-puncturing issues in the language. That serves to bind clients to implementation details anyway, in the absence of pImpl type techniques. Lacking the relevant semantics forces you to deal with the interface/implementation divide directly. This is not the case in Java or C#, which implement sane module systems and let you alter implementations without impacting clients.
 
If you consider C++ private/protected semantics relevant to your code design, it's time for a redesign.


I never talked about friend intentionally, because I don't think it's that useful and tends to cause the problems you list.

But again, the mere presence of a language feature doesn't completely invalidate other language features.

Heck, the C# and Java code that love so much requires you to put interface and implementation in the same file. You can't even hide your code in the same way the C header/source system does. The only time you don't see the entire implementation is when you are dealing with a library and only have the compiled metadata to go against.

Share this post


Link to post
Share on other sites
Promit    13246

I mean, as long as you're complaining about implementation in headers, you might as well also complain about templates which force implementation in headers.

"As long as we're complaining about Alzheimer's, we might as well also complain about cancer."


At this point you're not complaining about public/private/protected, you're just complaining about the header and compilation unit system which has long outgrown its usefulness and is being replaced with proper modules in a future C++ version once they nail down the spec.

Just to be clear, my claim is that private/protected semantics have no value in C++ as it exists today. Yes, the compilation model got us here. But as long as we're living with that, I simply reject any idea that these features accomplish anything but a false feel-good sense of "ah, totally encapsulated". Encapsulation in C++ requires polymorphic interfaces or pImpl, period. (Or in some cases, stripped headers, which are a messy game to play.) Once you apply these techniques, access semantics no longer have any meaning anyway.

 

 


Heck, the C# and Java code that love so much requires you to put interface and implementation in the same file. You can't even hide your code in the same way the C header/source system does. The only time you don't see the entire implementation is when you are dealing with a library and only have the compiled metadata to go against.

I've seen this complaint many times over the years - there is no file in these languages that sums up the public interface without the implementation details, unless of course you write up a polymorphic interface and implement it separately. The ability to see the public interface is instead consigned to IDE based metadata or code analysis tools. I have mixed feelings about this. But in the course of practical and professional work, the C++ version has created far more problems for me while the C# version is inconvenient at worst. Of course this leads back to the C++ compilation model, which is a disease that goes far beyond something as trivial as private/protected.

 

At the end of the day, I can't think of an instance across 15 years of personal and professional C++ development work where I've avoided a single bug or mistake by marking variables as private. The borderline cases are easily dealt with by naming convention. Since client code is bound by the compilation model to the total definition of the class anyway, you just don't get the expected benefits.

 

The primary goal of the post is to secure the end user of the API but the part about attacks was not bad.

No idea what you're talking about.

Edited by Promit

Share this post


Link to post
Share on other sites
Alundra    2316
No idea what you're talking about.

I edited the post because of the language mistakes :

"The primary goal of the post is about security for the end user of the API but the part about attacks was not bad."

Edited by Alundra

Share this post


Link to post
Share on other sites
Alberth    9529

...but it's still standard practice to use private extensively in code today, as it does provide a lot of benefit...

Common practice doesn't mean a lot; most programmers never ever question the habits they got used to, while learning to program. As such, you mostly observe patterns teached a decade or so ago.

A good example is setters and getters in Java.
Every Java tutorial you get is filled with them. As a result, you see everybody using these functions, even if they don't really add anything. If you do "public void setX(X newX) { this.x = newX; }" you can just as well drop the setter and getter, and just give access to the variable itself, since you're protecting nothing. There is one exception that I can think of, namely if you write a library where the public API accesses variables, and you want to be able to update the library without breaking the programs using it.
I know they're supposed to enhance modularity, but I have yet to see a case where you change the inner working of a class where the surrounding code isn't considered or touched. And it's easy enough to refactor abstraction/getter/setter functions in, if you need them.

So in most Java code, I don't see the need for getters and setters at all. Yet you continue to see these functions everywhere.


I do agree having protected/private is useful to guide intended use of the API (and I do miss the C++ protected notion in Java every now and then).
On the other hand, It's just guidance, something that can easily be expressed in a line of comment. Edited by Alberth

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this