views:

863

answers:

5

There was a question recently on SO (Why on earth would anyone use strncpy instead of strcpy?), which hade answers (answer 1, answer 2), that made me uncertain about other string functions with 'n' in their name, like snprintf (which I have been using extensively). Is snprintf safe to use? And generally, what are the safe functions from the 'n' family?

A: 

Beware: different platforms have different behaviors concerning null termination of a string passed to snprintf.

Jared Oberhaus
`snprintf` as specified in ISO C99 is guaranteed to null-terminate.
Pavel Minaev
That's what ISO C99 says: however, the behavior on certain platforms is different. You'll have to experiment and validate each platform to be sure.
Jared Oberhaus
Can you give an example of a platform that doesn't conform with standard C in this respoect?
Martin v. Löwis
Microsoft's variant, _snprintf(), doesn't terminate the destination if the buffer isn't large enough: http://msdn.microsoft.com/en-us/library/2ts7cx93.aspx
Michael Burr
+1  A: 

snprintf does guarantee that the buffer won't be overwritten, but it does not guarantee null-termination. use sprintf_s.

See http://msdn.microsoft.com/en-us/library/2ts7cx93%28VS.71%29.aspx

Drew Hoskins
I see someone has revealed which platform I was referring to...
Jared Oberhaus
Actually not, snprintf doesn't guarantees buffer overflows at all. It depends on the buffer size you provided, which can be incorrect
hab
It goes without saying that there is no CRT function that magically knows how big the buffer passed in actually is.
Drew Hoskins
Well, then it goes without saying that no CRT function is "safe", and there's not much point people going around pretending that appending _s to the names of them all breaks this rule ;-)
Steve Jessop
-1: You should clarify that you're talking about the broken Microsoft implementation and not the C standard.
R..
A: 

It is safe as you long as you provide the correct length for the buffer.

hab
Which length you provide (and whether or not you manually null terminate the end of the buffer yourself) depends on which platform you're on.
Jared Oberhaus
+5  A: 

strncpy() is an oddball function that is really misnamed - it's original purpose to to ensure that a buffer was completely initialized with the contents of a string (without overflowing the target) and the reminder of the buffer with zeros. As I understand it, the original purpose was to handle file system directory entries - the target buffer was not really a string in the same sense as the other strxxx() functions in the C library. The main problem with strncpy() is that if the source string is larger than the destination buffer, the result will not be null terminated.

Most of the other 'n' functions that deal with strings do properly terminate the string, but there are exceptions like Microsoft's bastardized _snprintf(). A proper C99 snprintf() will always null terminate the destination string (as long as the destination buffer has a size greater than 0).

There's a 'Technical Report', TR 24731 that proposes a set of boundary-checking alternatives for functions that deal with strings and memory buffers. One of the goals of the TR is to have the parameters, results and error behavior of the functions be more similar across the functions. The TR seems to have somewhat mixed acceptance, and I don't think it's widely implemented other than for Microsoft's compiler (I think MS was the main driver behind the TR). you can get more information here:

Even if you're not a fan of the proposals, I think they make for educational reading about the issues with existing functions.

Michael Burr
A: 

While snprintf will not overrun a buffer if you give it the correct arguments, please keep in mind that it shares all of the format string vulnerabilities with other members of the *printf family. For example, the %n specifier is nasty because it can be used by attackers to write arbitrary bytes to arbitrary memory locations. See FIO30-C. Exclude user input from format strings from the CERT C Coding Standards wiki.

Andrew Keeton