Basic Secure Coding Practices for C or C++

Wednesday, May 04, 2011

Keith Mendoza


These tips are not, I repeat, not intended to be a complete list of tips on writing secure code in C or C++.

These are things that, I believe, should be practiced by anyone who writes program in C or C++ no matter how low the security risk. I also believe that these same principles can be used in any programming languages.

Use Comments Wisely

I had a professor who once said "it's better to over-comment and make sure that everyone understands why your code is the way it is than to not put comment and annoy everyone that has to read your code."

Use comments to help "document" what your code is actually doing. Open-source software are notorious for not having any comments in their code. Many would argue that good code will explain what is happening, I agree to an extent.

The "why's" should be put as comment to explain why certain sections of code are the way they are.Obviously, over-commenting is just as bad since it clutters up the source code making things harder to read. Balance is needed to make comments useful.

Heed the warning messages

When a compiler gives a warning message it's for a good reason. Compiler warnings typically deal with your code's structure that could lead to potential problem with how your code is either executed or how data is presented to your code for processing.

If you are using a compiler that has an option to have all warnings on, you should do so. Make modifications to your code so that the warning message goes away; if at all possible don't simply do an explicit typecast (more on this in the next sections).

If for some reason, you have a compelling reason to leave your code in a way that the compiler gives a warning, make sure to put a comment in your source as to why the warning can be ignored.

Use the right data type for the data being handled

Don't use an int data type to store a char data; or use a float when you are only dealing with whole numbers; and use the right data type for the range of values that your variable will be holding.

Here's the deal: when you use a certain data type, that's memory being allocated for your application, and chances are this memory allocation is sandwiched between 2 code segments.

At the minimum this is extra memory that you are using needlessly and could affect either your application or the system's performance as a whole (think pagination). At the worst case, that could be an area that an attacker could write execution code in the stack that they can come back to at a later time.

Granted that most privilege escalations take advantage of being able to modify the code being executed because the application will write to memory locations past what it allocated; however, if you have a variable that uses up more space than the amount of data that you really care for, that's extra space for an attacker to use.

I think it's worth pointing out that the early computer viruses didn't target buffer overruns, they appended themselves to executables. The virus code executed along with the original executable; not like most of today's attack code where they left the executing application to crash when they're done.

Be wary of typecasts--especially implicit ones

Whenever you have to typecast from one data type to another you should check carefully what your typecasting and why. If you're using a method that either takes in or returns a certain data type, it would be best to find out why why they it returns that data type. We are going for ease of readability here.

Yes, I know that standard C functions like fgetc(), getc(), and getchar() returns int when they really only deal with character data. Well, there was a time in Windows when getc() can be used to read strings that are 4-characters long. It really irks me that C and C++ textbooks still provides examples where the return of these functions are stored in an int variable.

My point is, not just because the standards allows it--or even requires it--doesn't make it any less correct. I've seen this lead to all sort of confusion with people who first learn to program in the newer languages like Java or Python.

If for some reason that you are left with no recourse but to typecast, make sure to make it explicit. Not just because an int data can conveniently convert to a char data doesn't mean you should just use implicit typecasting.

Use the right data structure methods

Understand when to use a union, enum, or struct to define your data type, and know the implications of each. Figure out what the data structure will be used for. Enums work great for defining "one of these things" items and they can be used in switch-case statements and assigned unique values relative to members in the enum definition.

Unions work great for "can be a.." items; they amount of memory used is for the biggest "member". However, you have to be careful not to inadvertently use the wrong member and inadvertently typecast the data (compiler warnings will not help here at all).

Structures are probably the least confusing of them all. However, this bears repeating: make sure that all it's members actually belongs there. Don't simply create a struct type to save you from having to type a 20 parameters to your functions; to be honest there's probably something really wrong with your design.

Cross-posted from Home+Power

Possibly Related Articles:
Software Application Security Development Secure Coding hackers Software Security Assurance
Post Rating I Like this!
Susan V. James Excellent article - should require this as mandatory reading and get a signed agreement from all developers before they get their "Official Developer" card - oh, wait... there's no such thing, and that is part of the problem. Developers are required to deliver their work quickly and as cheaply as possible, and that often means contracting labor that cuts the corner of security either because they are ignorant (and ignorance comes cheaply), or they work for the low bidder for the project who has cut his expenses down to the bone in order to land the contract and/or increase his profit. There is either a lack of security awareness in the SDLC, or simply no time for it.

Once the code is delivered, the poor workmanship becomes largely the consumer's problem, not the developer's.
Keith Mendoza Susan,
I'm glad that you liked my blog post. It's sad to see that this is not common practice in the software development industry. However, I feel that if every developer is required to do this, it will become instinctive to them that it will get to the point that there will be no extra development time to implement this in every code that they write.
em vee Yes, a good post. Any attention to secure coding practice is better than none.

A coda, courtesy of Alan J Perlis, to final point about misusing structures to hide the design flaw inherent in many unrelated arguments:

"If you have a procedure with 10 parameters, you probably missed some"

The views expressed in this post are the opinions of the Infosec Island member that posted this content. Infosec Island is not responsible for the content or messaging of this post.

Unauthorized reproduction of this article (in part or in whole) is prohibited without the express written permission of Infosec Island and the Infosec Island member that posted this content--this includes using our RSS feed for any purpose other than personal use.