Click here to Skip to main content
15,885,278 members
Articles / Programming Languages / C
Tip/Trick

swprintf_s Safe? Maybe Not.

Rate me:
Please Sign up or sign in to vote.
4.67/5 (4 votes)
9 Feb 2010CPOL2 min read 35.3K   6   4
swprintf_s() and sprintf_s() are additions to VC++8, and were supposedly written to tolerate formatting errors and to avoid buffer overruns. They differ from their corresponding non-safe cousins swprintf() and sprintf() by taking an extra argument (the 2nd parameter), which is the size of the...

swprintf_s() and sprintf_s() are additions to VC++8, and were supposedly written to tolerate formatting errors and to avoid buffer overruns. They differ from their corresponding non-safe cousins swprintf() and sprintf() by taking an extra argument (the 2nd parameter), which is the size of the buffer passed as the first argument. The prototype for swprintf_s() is:

int swprintf_s(wchar_t *Buf, size_t sizeOfBuf, const wchar_t *format [, argument]...)
The following use of swprintf_s() would seem to be in keeping with the prototype declaration.
wchar_t buf[12];
...
swprintf_s(buf, sizeof buf, "%s%d", L"result", 2);
However, this code is likely to cause a crash in the next few statements following it, but not always.

If you change the code to

swprintf_s(buf, 12, "%s%d", L"result", 2);
it will correctly execute.

A close examination of the documentation reveals that the 2nd parameter is not a size, in spite of its type, but instead the number of characters in the buffer. The reason the first example crashes is because sizeof(wchar_t) is greater than 1. If we assume sizeof(wchar_t) == 2, then sizeof buf == 24, but since the 2nd argument is taken as the number of characters swprintf_s() thinks that it has a 48 byte memory area. So what? The format request only generates 8 characters. However, if you watch the memory area (with VS8) passed as the 1st parameter while swprintf_s() executes, you will see the Debug version clear to uninitialized all the bytes in the buffer beyond those in which it writes the formatted information. So if you pass the wrong size to swprintf_s(), it will spank you by overwriting your data.

The poor aspect of this design is avoidance of sizeof, which is the standard C/C++ operator for compile-time determination of memory sizes. Even though the type of the 2nd parameter would imply a sizeof value, this is not what the function expects. sizeof is the language's way of keeping byte counts out of a program, but swprintf_s()'s design forces character counts back into the program. Consider what would happen if the buffer size is changed. Is the programmer going to realize that all the character count arguments to swprintf_s() calls also need to be changed?

In order to be truly safe, the 2nd parameter needs to be coded as:

(sizeof buf)/(sizeof buf[0])
We divide the size of an array by the size of an array element, which provides the number of array elements. This is the expression that is needed as the 2nd parameter to swprintf_s() in order to keep your code independent of changes to the size of the buffer. Microsoft has incorporated this definition in the _countof() macro, which is not standard C, but is available in VS8 stdlib.h

As to why the function spends CPU time clearing the remaining buffer, I guess that it is an attempt to generate a quick failure if the wrong the size passed. I hope that this undocumented feature is only in the Debug version of the function.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



Comments and Discussions

 
Suggestiontemplate version Pin
smags1325-Sep-15 8:57
smags1325-Sep-15 8:57 
QuestionPossible theory. Pin
sasue1130-Nov-14 5:27
sasue1130-Nov-14 5:27 
Question4 days looking for one error! Pin
futureFAvorit328-May-13 2:11
futureFAvorit328-May-13 2:11 
GeneralThe 'clear' seems like a good idea Pin
supercat99-Feb-10 11:20
supercat99-Feb-10 11:20 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.