Let's be clear here.
- insecure is a matter of context, not a case of "the use of" a specific function. If I use memcpy insecurely on a process running as a user with little to lose, no setuid or any such flags, the "worst" I can do is get a shell for that user and go from there. To achieve privilege escalation you need to attack something you can fool into giving you higher privileges.
- C/C++ are not "dangerous tools". They are tools. Insert appropriate metaphor about dangerous DIY implement.
The fact is, as Rook has already said, C/C++ and other such other compiled-to-the-machine languages have a place in the world. They're for building fast systems, operating systems, system services etc. They afford you the ability to manage your own memory as you see fit. You're in control.
Unless you introduce some form of automatic memory management, there's no way of truly working out if you've gone past the allocated memory. So, ok, let's introduce a container. Now every memory access call that ever was needs to be checked. Is it in scope for that particular function? How many objects are pointing at it? Where are they in scope? Can I have pointers outside of the scope of the original reference and if so how do I keep track of it? Very quickly, you've got a virtual machine and so you have a managed language.
Also, as was demonstrated over on StackOverflow, it is possible to invoke
memcpy_s in a way that is insecure anyway. It doesn't really solve the fundamental problem, just makes it a little harder to make mistakes.
That is the difference. C/C++ is fancy assembly with all the power you need to do anything. Java/Python etc protect you from that at a price: speed and power.
You've said repeatedly over the course of today (I've followed the SO version too) that you still haven't got an answer as to how you develop securely with C/C++ on other systems like Linux. Well firstly, with VS2005/2008 I pretty much habitually set
CRT_SECURE_NO_DEPRECATE, but anyway, here's a few things you could do:
- You ask on StackOverflow. You take note, learn, read and re-read.
- Your compiler is (mostly) your friend. Listen to it. Use warnings. Turn them into errors. So
cl /W4 and
gcc -Wall -Werror -pedantic -std=c99. Yes, it is OTT in terms of error messages. But if you can't explain each one and justify why you're ignoring it, you don't understand your own code.
- Check your memory allocation.
valgrind's default invocation checks your allocations and deallocations mean you're not losing memory. If you've got memory leaks, you haven't thought enough about your code. It's a good sign you've got off-by-one errors, invalid bounds checking etc.
valgrind again. I've just picked this up, but look, there's an experimental over/under-run checker in valgrind. Will tell you if, for example, you crash off the end of the stack (possible, seeing as that's where most local variables are allocated) or outside the
splint a.k.a. secure lint, take note of its output. Again, if you can't explain any output it gives, you don't understand your code.
Inwardly digest the C Secure Coding Standard. Specifically relevant here:
- If you are using C++, use
boost::shared_ptr (and related; use the appropriate one). There is absolutely no argument to be
memcpying strings in C++ except for interaction with C. Even then
string.c_str(), please and leave the manipulations to C++.
- Dynamically link where possible. If you've statically linked any 3rd party code into your app and that turns out to have a security problem, you've got it too and you have to redistribute your image too. Not only are shared objects just more convenient generally, you also get security updates by default. I know there are cases where you can't, that's why I say "where possible".
- Build this into your development cycle.
- Hope you didn't miss something.
- Keep up with relevant security community updates that might be relevant.
- Be nice to the security community. Acknowledge sec vuln's, take steps to fix them. All code has (or had them) bugs if it is worth running. Simple as that.
At the end of the day I don't think the problem is solved by "secure" functions. I think the problem is solved by the use of some decent tools, a proper development process that rejects poor code from critical versions (late betas and release candidates) and finally an awareness of good practice/current issues.
memcpy_s isn't part of the C99 standard. It's an extension to the C library (as in not part of the core) and therefore not guaranteed to be on the platform I'm using.
memcpy is. For a software project that needs to be compiled cross platform, that'll probably be the deciding factor in which function to use.