There are many security risks coming from having close contact to the hardware as opposed to using well-tested and proved APIs from high level programming languages. It is much easier to cause a buffer overflow in C than in a language such as Java.

What are the risks or vulnerabilities (e.g. buffer overflows) that every C programmer should be aware of (I.E. vulnerabilities relevant to C programmers)? What problems could these lead to? How to avoid them, and what are common mistakes causing these to occur in programs?

  • What about this list: owasp.org/index.php/Category:OWASP_Top_Ten_Project What more is needed than this?
    – S.Lott
    Apr 27, 2011 at 17:36
  • 2
    @S.Lott: It seems to be very much about security issues in web development. There seems to be more resources on that in general than what I am actually asking for, it seems.
    – Anto
    Apr 27, 2011 at 17:37
  • @Anto: Please update the question to distinguish between all the resources on security and the security you're asking about.
    – S.Lott
    Apr 27, 2011 at 20:50
  • @S.Lott: I'm not sure what you mean. I ask for security which is of importance to most C programmers, that is, things like buffer overflows and other things which are possible in C.
    – Anto
    Apr 27, 2011 at 20:53
  • @Anto: "There seems to be more resources on that [web security?] in general than what I am actually asking for" Seems to say that you're asking about some security that isn't web security. True? If so, please update the question to explain what you're looking for. False? Then you are asking about web security, in which case, why isn't the OWASP list mentioned in your question?
    – S.Lott
    Apr 27, 2011 at 20:55

4 Answers 4


Buffer overflows are a big one. Nothing in C is range-checked by default, so it's very easy to overwrite a buffer. There's a standard library function, gets(), that cannot be stopped from overflowing the buffer, and should almost never be used.

There are some implementation-level techniques to hinder exploitation, such as scrambling heap blocks, but that won't stop buffer overflows in local buffers, which can often do interesting things like change the address a function will return to.

There is no good general solution in C. Many library functions have versions that will limit the amount they will write. although calculating that can be clumsy. There's software that can detect heap buffer overflows in test, as long as the appropriate test is run, and stack overflow will often show up as a crash in testing. Other than that, it's a matter of careful coding and code review.

A related issue is the problem of writing into a buffer too small by one character, forgetting that a C string that's n characters long requires n+1 characters in memory, because of the '\0' terminator. If the attacker can manage to store a string without the terminator, any C function expecting a string will continue processing until it hits a zero byte, which could result in copying or outputting more information than is desired (or hitting protected memory for a DOS attack). The solution, again, is awareness, care, and code reviews.

There's another risk with the printf() family. If you ever write char * str; ... printf(str);, you're setting yourself up for problems if str contains a '%' when printed. The %n format directive allows printf() to write into memory. The solution is printf("%s", str); or puts(str);. (Also, use the C99 snprintf() instead of sprintf().)

Using unsigned integers, particularly as loop indexes, can cause problems. If you assign a small negative value to an unsigned, you get a large positive value. That can undermine things like processing only N instances of something, or in limited functions like strncpy(). Examine all unsigned integers. You might want to avoid unsigned short, since a large value in one of those will convert to a large positive value in an int.

Don't forget that a character constant, in C, is actually an int. Writing something like char c; while((c = getchar()) != EOF) ... can easily fail, since EOF won't be representable in a char.

There's a lot more characteristic C mistakes I can think of, but these could cause security problems.

  • There's no need to use printf("%s", str) for a naked string when puts(str) will do the same job.
    – Blrfl
    Apr 27, 2011 at 20:22
  • @Blrfl but puts appends a newline character while printf does not.
    – user4595
    Oct 28, 2011 at 19:05
  • Could also do fputs(str, stdout), which doesn't.
    – Blrfl
    Oct 28, 2011 at 19:15
  • As to integer overflow: Using signed ints is no solution, as overflowing them will cause UB. The only (painful) solution is to either formally prove that you will never overflow, or check at runtime (but check correctly, which is also tricky without overflowing in the check).
    – sleske
    Jan 12, 2016 at 9:44
  • @DavidThornley: C11 & C++14 standard removed gets() function from standard library due to its dangerousness.
    – Destructor
    Jan 28, 2016 at 14:30

Some of the C-specific risks include: buffer overflows, formatting string attacks and integer overflows.

  • 1
    There's nothing C-specific about buffer overflows - any language with pointers can have this. Integer overflows apply to just about any language, and can easily happen in managed code too.
    – Steve
    Apr 27, 2011 at 17:55
  • 1
    @Steve, its not really pointers that cause that problem but how the language doesn't enforce array bounds.
    – Doug T.
    Apr 27, 2011 at 18:06
  • 2
    @Steve the question was not asking about stuff that only concerns C, but something that C programmers should be aware of. Apr 27, 2011 at 18:16
  • 1
    @Steve: C is unusually susceptible to buffer overflows, partly because of the lack of support for range-checking, and the number of library functions that will happily overflow buffers for you. Apr 27, 2011 at 18:17
  • I understand the question is asking about C in particular, but I think it is worth clarifying in case the answer is read out of context that these risks are more general. In particular developers of managed code are (IMHO) far too complacent about security, and integer overflows in particular affect most languages.
    – Steve
    Apr 27, 2011 at 18:45

Here is an easy to miss risk that can cause problems which will take hours to fix.

Consider the following code, which will compile with no problems.

if(lpstr_current_state = CONST_EMERGENCY_STATE_HOLY_CRAP)

When you check to see if lpstr_current_state is in CONST_EMERGENCY_STATE_HOLY_CRAP you're actually assigning. It is better to always put the constant variable on the left. When you put the constant on the left, then the compiler will fail because you can't assign a value to a variable.

if(CONST_EMERGENCY_STATE_HOLY_CRAP = lpstr_current_state)

Then you can easily say to yourself, "Holy crap, that could have been bad", while fixing the code to read ...

if(CONST_EMERGENCY_STATE_HOLY_CRAP == lpstr_current_state)
  • 7
    That is easy for a compiler to catch and flag as a warning, unlike some other problems. Unfortunately, not all compilers make it easy to do. Apr 27, 2011 at 17:36
  • 2
    That can happen in languages other than C, any language that uses = and ==. Apr 27, 2011 at 17:41
  • 3
    This is also not really a security vulnerability, this is a bug. Apr 27, 2011 at 17:48
  • 1
    These are called Yoda conditions.
    – user11408
    Apr 27, 2011 at 17:51
  • 2
    @Kristofer Hoch: If we're going to call any likely C bug a risk, and consider it here, we're going to need a much larger forum. Apr 27, 2011 at 18:23

There is just one security risk: The fact that there are people outside who will do their best to catch any vulnerability in your software and to exploit it for their own gain. Everything else follows from there.

So when you think "nobody in their right mind would ... ", then you need to think immediately "except someone who wants to hack into other people's computers would do exactly that".

The biggest consequence is that whenever you react to events outside (for example, by processing data delivered from the outside), you must assume that this data was under control of your worst enemy.

  • While I would agree with paragraph two and three, putting all the blame on the attacker is a bit thick in my eyes. It always takes two for a successful attack: A programmer who screws up, and an attacker who catches the programmer in the act. However, the security vulnerability is there before the attacker can exploit it. And for that, the programmer is to be blamed. Aug 26, 2016 at 6:35

Not the answer you're looking for? Browse other questions tagged or ask your own question.