mab0189
mab0189

Reputation: 136

Behaviour of snprintf with %s at end of format string

I am building commands with snprintf() that i want to execute with system(). I noticed that the last character is missing when i use %s at the end of the format string but when i am adding an extra space after the %s it works as i would expect. Why does this happen? I think i am missing something. I appreciate your help!

Here is an minimal example:

#define INTERFACE "can0"

int size;
char *command = NULL;

size = snprintf(command, 0, "/sbin/ifdown %s", INTERFACE);
command = malloc(size);
snprintf(command, size, "/sbin/ifdown %s", INTERFACE);

Upvotes: 1

Views: 1240

Answers (2)

Werner Henze
Werner Henze

Reputation: 16726

en.cppreference says (emphasize is mine)

int snprintf( char *restrict buffer, size_t bufsz, const char *restrict format, ... ); (4)

  1. Writes the results to a character string buffer. At most bufsz - 1 characters are written. The resulting character string will be terminated with a null character, unless bufsz is zero. If bufsz is zero, nothing is written and buffer may be a null pointer, however the return value (number of bytes that would be written not including the null terminator) is still calculated and returned.

So your first call returns the number of characters that would be written excluding the terminating null character. Your second call to snprintf says that size characters should be written including the terminating null character.

So the fix should be to allocate a bigger buffer and to pass size+1 in the second call.

command = malloc(size+1);
snprintf(command, size+1, "/sbin/ifdown %s", INTERFACE);

You don't show the code with the extra space. But I guess you have added it to the first call of snprintf and maybe also to the second call. In that case your first snprintf returns a size that is one higher. The second snprintf cannot write the additional space, but with the higher size it can now write the string as you expect it.

Upvotes: 2

Yakov Galka
Yakov Galka

Reputation: 72479

snprintf returns the number of characters printed not including the null terminator. Therefore when you pass that size back to snprintf it figures out that your buffer is one char short. Fix it as follows:

size = snprintf(command, 0, "/sbin/ifdown %s", INTERFACE);
command = malloc(size+1);
snprintf(command, size+1, "/sbin/ifdown %s", INTERFACE);

Upvotes: 3

Related Questions