Updates to documentation for string printf functions#3411
Conversation
* Fix description of behaviour when encoding errors occur. * Clarify truncation behaviour (matching vsnprintf_s family of functions). * Add error condition table (matching vsnprintf_s family of functions).
* Fix description of behaviour when encoding errors occur. * Clarify truncation behaviour of vsnprintf_s family of functions. * Clarify error condition table for vsnprintf_s family of functions.
* Clarify the return value behaviour of snprintf family of functions. * Clarify truncation behaviour of snprintf family of functions.
…th snprintf family of functions: * Fix description of behaviour when encoding errors occur. * Clarify the return value behaviour of vsnprintf family of functions. * Clarify truncation behaviour of vsnprintf family of functions.
|
@adr26 : Thanks for your contribution! The author(s) have been notified to review your proposed change. |
|
#label:"aq-pr-triaged" |
|
Thank you very much, @adr26. I am referring this to the dev who works in this area for review. They are preparing for a conference right now so there may be some delay before he can look at it. |
|
@TylerMSFT - thanks for the update: I put this together on the back of some work I'd done for a codebase my team owns, which ships internally with sources, and where the codebase still has to support some clients who compile it with VS2008(!) and VS2013. C99-conformant We implemented wrappers for the Having done that, I wanted to make sure that what I'd learned about the differences between the behaviour I'd observed in my characterisation and what was in the docs was preserved for posterity: mostly for my sanity, in case I ever have to look at that code again, but also for the benefit of the wider community. As such, I hope this contribution is helpful, but it isn't very high-priority. I hope your dev's preparations go well, and I'll be glad to discuss further once they've got time to look at it: thank you again! Andrew R |
|
@adr26, you probably thought this was lost and forgotten. But no-I finally had time to go through it in detail. I'm going to close this, but nothing is lost. I took all this material and converted it to a table in this PR I thought a table would be a faster way for people to process the info that otherwise takes paragraphs to explain. You are welcome to review that PR because this space provides plenty of opportunity for errors. I tested the claims in the new tables against VS 2022. |
The behaviour of
vsnprintf()withcount == 0andbuffer != NULLis to return the length of the formatted data, rather than returning-1— as the documentation currently states. I have cross-referenced the behaviour ofvsnprintf()with the C specification, and confirmed that the implementation behaviour (returning the length of the formatted data) conforms to the C specification and is correct. Therefore, the currentvsnprintf()documentation is incorrect and needs to be updated.After making this observation, I conducted a broader review of the documentation for the
*sn[w]printf*family of functions, making these updates as a result.In general, I've corrected a number of errors in the description of the behaviour of the
*sn[w]printf*family of functions, and have aligned the information for:_snprintf_s()/_snwprintf_s()and_vsnprintf_s()/_vsnwprintf_s()snprintf()/_snprintf()/_snwprintf()andvsnprintf()/_vsnprintf()/_vsnwprintf()A detailed description of the problems addressed on each page is given below:
_snprintf_s()/_snwprintf_s():Add description of behaviour which occurs when an encoding error occurs during formatting — setting
errnotoEILSEQin all cases and either returning a negative value for a string conversion specifier, or skipping the character for a character conversion specifier.Clarify that in cases where truncation does not occur, null-termination is performed
Clarify truncation behaviour:
count < sizeOfBuffer, but formatted data> count, then formatted data is truncated tocountcharacters, null-terminated and -1 is returned with no error handler / update toerrnocount == _TRUNCATE, and formatted data>= sizeOfBuffer, then formatted data is truncated to(sizeOfBuffer - 1)characters, null-terminated and -1 is returned with no error handler / update toerrnocount >= sizeOfBuffer, formatted data>= sizeOfBuffer, andcount != _TRUNCATE, the invalid parameter handler is invoked. If continued, the functions truncate the buffer to an empty string, return -1 and seterrnotoERANGEClarify error handling behaviour:
bufferisNULL, anEINVALerror occurs if (and only if) eithercountorsizeOfBufferare!= 0(if both are 0, no error occurs and 0 is returned)EINVALerror does not occur in all cases wherecount == 0, only when one of the other conditions are met (countcannot be negative, assize_tis unsigned)sizeOfBuffer(notcount!)== 0, and additionally if buffer is notNULL, then anEINVALerror occursAdd copy of error conditions table from
_vsnprintf_s()/_vsnwprintf_s().snprintf()/_snprintf()/_snwprintf():Add description of behaviour which occurs when an encoding error occurs during formatting — setting
errnotoEILSEQin all cases and either returning a negative value for a string conversion specifier, or skipping the character for a character conversion specifier.Clarify truncation behaviour:
snprintf(), clarify that null-termination by writing tobuffer[count-1]is only performed ifcount != 0._snprintf()/_snwprintf(), clarify that non-terminated truncation is performed only whenbuffer != NULL(ifbuffer == NULLandcount != 0, it is an error and if ifbuffer == NULLandcount == 0, the length of the formatted data is returned)._vsnprintf_s()/_vsnwprintf_s():Add description of behaviour which occurs when an encoding error occurs during formatting — setting
errnotoEILSEQin all cases and either returning a negative value for a string conversion specifier, or skipping the character for a character conversion specifier.Clarify that in cases where truncation does not occur, null-termination is performed
Clarify truncation behaviour:
count >= sizeOfBufferand formatted data>= sizeOfBuffer, then only if alsocount != _TRUNCATEthe invalid parameter handler is invoked, etc.Clarify error handling behaviour:
bufferisNULL, anEINVALerror occurs if (and only if) eithercountorsizeOfBufferare!= 0(if both are 0, no error occurs and 0 is returned)EINVALerror does not occur in all cases wherecount == 0, only when one of the other conditions are met (countcannot be negative, assize_tis unsigned)sizeOfBuffer(notcount!)== 0, and additionally if buffer is notNULL, then anEINVALerror occursUpdate error conditions table to correct from
count == 0tosizeOfBuffer == 0as the condition required for anEINVALerror (whenbuffer != NULL).vsnprintf()/_vsnprintf()/_vsnwprintf():Add description of behaviour which occurs when an encoding error occurs during formatting — setting
errnotoEILSEQin all cases and either returning a negative value for a string conversion specifier, or skipping the character for a character conversion specifier.Clarify that in cases where truncation does not occur, null-termination is performed
Clarify truncation behaviour:
vsnprintf(), clarify that null-termination by writing tobuffer[count-1]is only performed ifcount != 0._vsnprintf()/_vsnwprintf(), clarify that non-terminated truncation is performed only whenbuffer != NULL(ifbuffer == NULLandcount != 0, it is an error and if ifbuffer == NULLandcount == 0, the length of the formatted data is returned).vsnprintf(), clarify that ifcount == 0andbuffer != NULL, the length of the formatted data is returned, rather than-1(as is the case for_vsnprintf()/_vsnwprintf()).To verify the behaviour of these functions, I constructed the attached test code (printf.zip). The updated descriptions of these functions' behaviour can be verified using the output from this: