This is inspired by this question and the comments on one particular answer in that I learnt that strncpy
is not a very safe string handling function in C and that it pads zeros, until it reaches n
, something I was unaware of.
Specifically, to quote R..
strncpy does not null-terminate, and does null-pad the whole remainder of the destination buffer, which is a huge waste of time. You can work around the former by adding your own null padding, but not the latter. It was never intended for use as a "safe string handling" function, but for working with fixed-size fields in Unix directory tables and database files. snprintf(dest, n, "%s", src) is the only correct "safe strcpy" in standard C, but it's likely to be a lot slower. By the way, truncation in itself can be a major bug and in some cases might lead to privilege elevation or DoS, so throwing "safe" string functions that truncate their output at a problem is not a way to make it "safe" or "secure". Instead, you should ensure that the destination buffer is the right size and simply use strcpy (or better yet, memcpy if you already know the source string length).
And from Jonathan Leffler
Note that strncat() is even more confusing in its interface than strncpy() - what exactly is that length argument, again? It isn't what you'd expect based on what you supply strncpy() etc - so it is more error prone even than strncpy(). For copying strings around, I'm increasingly of the opinion that there is a strong argument that you only need memmove() because you always know all the sizes ahead of time and make sure there's enough space ahead of time. Use memmove() in preference to any of strcpy(), strcat(), strncpy(), strncat(), memcpy().
So, I'm clearly a little rusty on the C standard library. Therefore, I'd like to pose the question:
What C standard library functions are used inappropriately/in ways that may cause/lead to security problems/code defects/inefficiencies?
In the interests of objectivity, I have a number of criteria for an answer:
- Please, if you can, cite design reasons behind the function in question i.e. its intended purpose.
- Please highlight the misuse to which the code is currently put.
- Please state why that misuse may lead towards a problem. I know that should be obvious but it prevents soft answers.
Please avoid:
- Debates over naming conventions of functions (except where this unequivocably causes confusion).
- "I prefer x over y" - preference is ok, we all have them but I'm interested in actual unexpected side effects and how to guard against them.
As this is likely to be considered subjective and has no definite answer I'm flagging for community wiki straight away.
I am also working as per C99.
There is often a strtok_r.
For realloc, if you need to use the old pointer, it's not that hard to use another variable. If your program fails with an allocation error, then cleaning up the old pointer is often not really necessary.
basename()
anddirname()
aren't threadsafe.Another answer, since these are not really related,
rand
:In almost all cases,
atoi()
should not be used (this also applies toatof()
,atol()
andatoll()
).This is because these functions do not detect out-of-range errors at all - the standard simply says "If the value of the result cannot be represented, the behavior is undefined.". So the only time they can be safely used is if you can prove that the input will certainly be within range (for example, if you pass a string of length 4 or less to
atoi()
, it cannot be out of range).Instead, use one of the
strtol()
family of functions.Let us extend the question to interfaces in a broader sense.
errno
:technically it is not even clear what it is, a variable, a macro, an implicit function call? In practice on modern systems it is mostly a macro that transforms into a function call to have a thread specific error state. It is evil:
The forthcoming standard gets the definition of
errno
a bit more straight, but these uglinesses remainA common pitfall with the
strtok()
function is to assume that the parsed string is left unchanged, while it actually replaces the separator character with'\0'
.Also,
strtok()
is used by making subsequent calls to it, until the entire string is tokenized. Some library implementations storestrtok()
's internal status in a global variable, which may induce some nasty suprises, ifstrtok()
is called from multiple threads at the same time.The CERT C Secure Coding Standard lists many of these pitfalls you asked about.