Submitter:Fred J. Tydeman
Submission Date: 2020-09-02
Document: WG14 N2571
Title: N2571: snprintf
Reference Documents: N2478, N2495

Summary

One reading of snprintf has ambiguous or contradictorary statements.

"A if and only if B and C" can be parsed two ways:

I believe it would be clearer if done as:

In the returns section (paragraph 3) is an "if and only if" statement. If the second part of that is false, then the entire first part must be false. That means, if n is less than the return value [second part false], then the output is NOT complete and the output is NOT null terminated [first part false]. However, the description (paragraph 2) says that the output is null terminated for this case.

I also find paragraph 2:

Otherwise, ..., and a null character is written at the end of the characters actually written into the array.

confusing for the case where nothing is written. Is a null character written? I assume yes.

char buf[99]; 
rc = snprintf(buf, 0, "", 42);   /* rc == 0, buf is left alone */
rc = snprintf(buf, 1, "", 42);   /* rc == 0, buf is "\0" */ 
rc = snprintf(buf, 9, "", 42);   /* rc == 0, buf is "\0" */ 
rc = snprintf(buf, 0, "%i", 42); /* rc == 2, buf is left alone */ 
rc = snprintf(buf, 1, "%i", 42); /* rc == 2, buf is "\0" */ 
rc = snprintf(buf, 2, "%i", 42); /* rc  == 2, buf is "4\0" */ 
rc = snprintf(buf, 9, "%i", 42); /* rc ==  2, buf is "42\0" */

Most implementations do null-terminate the output for small n, but I have found at least one implementation that does not null-terminate the output when n is less than the return value.

Technical Corrigendum:

In 7.21.6.5 The snprintf function: Change in paragraph 3 (Returns):

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

to:

Unless either n is zero or the return code is negative, the output is null-terminated. The output has been completely written if and only if the returned value is both nonnegative and less than n.

or:

Unless either n is zero or the return code is negative, the output is null-terminated. The output has been completely written if and only if the nonnegative returned value is less than n.

The same fix needs to also be applied to