I have always wondered whether public, protected, and private has security implications post compilation.
Since you're asking about C++, I'd say the answer is "not per se" (unless this leads you to shoot yourself in the foot down the line somehow). The reason (and this is something I'd really like to emphasize compared to the other explanations) is that in C++, almost all type information exists only at compile time. The compiler may include a little bit of type information in the binary to facilitate stuff like dynamic_cast
, but otherwise it's done away with by and large even by the time the compiler outputs assembly language, let alone machine code. This is true even for C; a typical CPU has no idea if the address you're telling it to jump to truly holds the entry point of a function that takes and returns a double
or if it actually holds a char
in a list of rutabaga varieties—it just jumps and attempts to treat the next series of bits it encounters as an instruction, even if this leads to disaster. Likewise, no model of CPU I've ever heard of understands what a C++ class is, let alone varying degrees of class member access.
When people talk about security vulnerabilities in a programing context, they generally mean ways to get the program to perform other-than-intended behavior from the outside at runtime. A classic example is failing to check that user input can fit into a fixed-size buffer before storing it there: too-large input can cause your program to write the input past the end of the buffer in memory. With sufficient knowledge, an attacker might be able to craft input to that part of the program that will be written to a location the processor will try to proceed from later, allowing them to take control of the process.
Since member access specifiers like private
and protected
aren't represented directly in the binary, they wouldn't be said to have "security implications" in that sense. Rather, private
and protected
are to shield users of a public interface you're designing from depending on parts of the code that you imagine they'd rather not depend on, generally because you don't want to make the same guarantees about them that you do for the public API. They're very much for the benefit of human programmers and don't do anything on their own to guarantee correct program behavior at runtime. On that note, if you have some insecure code, it doesn't help to make it non-public
; it's still getting run at some point, presumably, so the vulnerability may still be exploitable through some outside interface that leads to that code path. Instead, you should fix it and alert anyone who might be affected.
In general, if you want to know what sorts of things in your C++ code do exist in some direct way at runtime and how, a great thing to do is to have your compiler stop after compilation proper and output assembly. g++
takes the -S
flag for this purpose, for instance, and you can pick between att
and intel
syntax with -masm=[DIALECT]
. You can also walk through your program instruction-by-instruction in a debugger like gdb
(see the stepi
and nexti
commands there, and maybe also the documentation for TUI mode which is very helpful when doing this).
If you're not familiar with the instructions and features supported by the processor you're targeting, you can learn about it by reading the programmer's manuals for the processor, which are often freely available; for x86 those are Intel's. You can also pick up a more tutorial-style book about working close-to-the-metal (I like Low-Level Programming by Igor Zhirkov).
C++-centric resources do often make it clear when something has runtime implications if it's required by the standard. However, the standard gives a lot of latitude to compiler authors at the hardware level as C++ is designed to be portable. As such, in order to develop an intuition for how your code might look post-compilation, I'd say it's easier to look at things from the hardware side for starters. You know that whatever's happening it must be terms the processor can understand, and there's only so many things you can say to a given processor. A bit past that, it can help to study how C compilers work in order to get a foothold—C is much simpler and closer-to-the-metal than C++ on the whole, so it's easier to understand from that angle, and much of the most "dangerous" parts of C++ are the parts that are shared with C or closeby to them. Studying how the operating system you're targeting works in detail is also helpful, especially its process model and memory management features (provided that you're not writing code to run on bare metal or the like).
Things are different if you're running code on an interpreter. C++ generally isn't run this way of course, but with many "higher-level" languages it's possible to exploit the behavior of the interpreter in a way that's far above the level of the processor, such as the classic case of trying to get a web server to send malicious SQL commands to a database. Of course, if you write an interpreter in C++, you can open up that whole can of worms, but that's not a C++-specific topic exactly.
As a postscript, there actually is a sense in which member access specifiers can have a direct effect on the behavior of your program at runtime. If you put two separate sections in a class with the same access specifier, the compiler is free to reorder them. For instance, with
class C {
public:
int n;
public:
int m;
};
the compiler is free to put m
before n
in memory. If your program's behavior depends on the data members of instances of C
being laid out a certain way, this may cause bugs, depending on the compiler. I imagine that's not quite what you had in mind, though.
class
declaration in a header file, but it's language-agnostic), and COM is... hard to explain, but I guess I'd explain COM as a way to "export" classes and other types from a Windows DLL so they can be reused by other applications without needing to statically-link anything. It's how OLE-DB, ActiveX, OLE, WinRT, VB6, VBA, Office Automation and more... just work. Because COM basically lets you export a C++class
so that a VBScript or Word document can use it matters how you design it, hence my link to COM licenses.reinterpret_cast
does not work with DCOM. In fact, DCOM will be secure and trusted provided the remoted object's interface doesn't expose secrets via public properties.