Can vsnprintf return negative value of magnitude greater than 1?

1.8k views Asked by At

Can vsnprintf() return a negative value of magnitude greater than 1? If so, under what circumstances does it do so?

I tried to use %ls as format specifier for a char array and also tried to copy larger than what array was allocated. In both cases I am getting -1 as return value.

2

There are 2 answers

5
Kerrek SB On

Yes it can, as in "it is allowed to". The circumstances depend on your platform and are not specified or regulated in any way. The only portable thing to do with the return value is to check it for < 0 to see if there was an error.

From the standard (7.21.6.12 (3), vsnprintf):

the null-terminated output has been completely written if and only if the returned value is nonnegative and less than n.

Any given platform may of course make additional guarantees about the return value; consult your documentation.

0
Jonathan Leffler On

The C99 standard says:

§7.19.6.12 The vsnprintf function

#include <stdarg.h>
#include <stdio.h>
int vsprintf(char *restrict s, size_t n, const char *restrict format, va_list arg);

Description

¶2 The vsnprintf function is equivalent to snprintf, with the variable argument list replaced by arg, which shall have been initialized by the va_start macro (and possibly subsequent va_arg calls). The vsnprintf function does not invoke the va_end macro.245) If copying takes place between objects that overlap, the behavior is undefined.

Returns

¶3 The vsnprintf function returns the number of characters that would have been written had n been sufficiently large, not counting the terminating null character, or a negative value if an encoding error occurred. Thus, the null-terminated output has been completely written if and only if the returned value is nonnegative and less than n.

245) As the functions vfprintf, vfscanf, vprintf, vscanf, vsnprintf, vsprintf, and vsscanf invoke the va_arg macro, the value of arg after the return is indeterminate.

And, since it is defined in terms of snprintf(), here's that section:

§7.19.6.5 The snprintf function

#include <stdio.h>
int snprintf(char *restrict s, size_t n, const char *restrict format, ...);

Description

¶2 The snprintf function is equivalent to fprintf, except that the output is written into an array (specified by argument s) rather than to a stream. If n is zero, nothing is written, and s may be a null pointer. Otherwise, output characters beyond the n-1st are discarded rather than being written to the array, and a null character is written at the end of the characters actually written into the array. If copying takes place between objects that overlap, the behavior is undefined.

Returns

¶3 The snprintf function returns the number of characters that would have been written had n been sufficiently large, not counting the terminating null character, or a negative value if an encoding error occurred. Thus, the null-terminated output has been completely written if and only if the returned value is nonnegative and less than n.


It doesn't say it will return -1 on an error; just any negative value. So yes, it is allowed to give a negative value with a magnitude greater than 1 on an error.


Microsoft's Versions

Note that Microsoft's specification for vsnprintf for Visual Studio 2015 says:

vsnprintf returns the number of characters written, not counting the terminating null character. A return value of -1 indicates that an encoding error has occurred. If the buffer size specified by count is not sufficiently large to contain the output specified by format and argptr, the return value of vsnprintf is the number of characters that would be written if count were sufficiently large. If the return value is greater than count - 1, the output has been truncated.

Both _vsnprintf and _vsnwprintf return the number of characters written if the number of characters to write is less than or equal to count; if the number of characters to write is greater than count, these functions return -1 indicating that output has been truncated. The return value for all functions does not include the terminating null, if one is written.

Note that this was not always the case:

Beginning with the UCRT in Visual Studio 2015 and Windows 10, vsnprintf is no longer identical to _vsnprintf. The vsnprintf function complies with the C99 standard; _vnsprintf is retained for backward compatibility.

For comparison, the Visual Studio 2013 documentation says:

vsnprintf, _vsnprintf, and _vsnwprintf return the number of characters written if the number of characters to write is less than or equal to count; if the number of characters to write is greater than count, these functions return -1 indicating that output has been truncated. The return value does not include the terminating null, if one is written.

The comparable pages for snprintf() are: