int snprintf(char* s, size_t n, const char * format, ...);
snprintfwrites the format string up ton-1characters tos.snprintfadds the null-terminator automatically.- The return value is the number of characters written if n had been sufficiently large to copy the whole format string.
- To check if the entire string has been written, check if
ret < n.
char myname[5];
// ruleid: snprintf-insecure-use
int ret = snprintf(myname, 10, "0123456789");There are two issues here:
- We're writing
10character intomynamewhich is 5 bytes. That's a buffer overflow. - Even if
mynamewas big enough, we're only copying 9 characters from the original string because the null-terminator is added bysnprintfand it only copies up ton-1characters.
char name2[5] = "1234";
// ruleid: snprintf-insecure-use
int len = snprintf(0, 0, "My name is: %s", myname);
char *p = (char*) malloc(len);
snprintf(p, len, "My name is: %s", myname);snprintf(NULL, 0, ...); (the first parameter can also be anything in this
case) is a popular way to figure out the length of a format string at runtime.
The manual says If n is zero, nothing is written, and s may be a null pointer.
However, we're not accounting for the extra null-terminator added by snprintf
in malloc(len). As a result, the last character of the string is not written
to p. If we print the value of p, we'll only see 123.
- Is the size of
s(the destination) big enough for all final strings?- This is specially important if some parts of the string are user-controlled.
- What are we doing with the value of
snprintf? Are we considering the automatic null-terminator?