From: Norman Diamond on
I was really surprised when Visual Studio 2005 gave a warning that function
_snwprintf was declared with old syntax. I couldn't quite figure out what
syntax _snwprintf was declared with. However, some investigation revealed
that Microsoft declared _snwprintf to be deprecated for security reasons.
There is some difference between a VC++ built-in header declaring a function
with old syntax and a company declaring a function to be deprecated.
Perhaps the maker of Visual Studio 2005 could be informed of the difference?

On figuring out that _sntprintf should be replaced by _sntprintf_s, I tried
to find it in MSDN. The search function of MSDN library United States found
the page for _snwprintf_s in MSDN library Korea but not in MSDN library
United States. Some manual searching found it in MSDN library United
States.

Now for some strange looking statements in page
http://msdn2.microsoft.com/en-us/library/f30dzcf6.aspx

First are two important statements which are only a bit strange:
> sizeOfBuffer
> The size of the storage location for output. Size in bytes for
> _snprintf_s or size in words for _snwprintf_s.
> Count
> Maximum number of characters to store, or _TRUNCATE.

OK, the sizeOfBuffer parameter is the same as the count parameter of the old
_snwprintf function. This really specifies the size of the buffer. The new
Count parameter specifies a maximum number of characters. I suppose the
dual limit is a convenience, but I don't understand how the level of
security improves. The size of the buffer is still specified the same way
even though the parameter name has changed, and the new Count parameter
specifies a different alternative limit instead of the size of the buffer.

> _snprintf_s returns the number of characters stored in buffer, not
> counting the terminating null character. _snwprintf_s returns the number
> of wide characters stored in buffer, not counting the terminating null
> wide character.

This looks terrible. Actually _snwprintf_s looks mostly OK, since the
programmer wants to do calculations on the number of wide characters and
keep track of how much space remains in the buffer. But why does
_snprintf_s return the number of characters instead of the number of bytes?
If a programmer is using the ANSI version then the programmer wants to do
calculations on the number of bytes in order to keep track of how much space
remains in the buffer. I also hope that _snwprintf_s doesn't have a split
personality on the treatment of surrogate pairs.

> In C++, using these functions is simplified by template overloads; the
> overloads can infer buffer length automatically (eliminating the need to
> specify a size argument) and they can automatically replace older,
> non-secure functions with their newer, secure counterparts. For more
> information, see Secure Template Overloads.

I'm not sure how Secure Template Overloads can infer buffer length
automatically, but maybe they call some undocumented memory management
functions, so OK, I read that page too.

http://msdn2.microsoft.com/en-us/library/ms175759.aspx
> To enable template overloads for the count functions, define
> _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT to be 1. Before doing so,
> however, make sure that your code passes the count of characters, not the
> size of the buffer (a common mistake).

Um, no wonder it's common for my code to pass the size of the buffer instead
of the count of characters. Look again at the sizeOfBuffer parameter to
_sntprintf_s and the count parameter to the old _sntprintf function. In the
Unicode version it's supposed to be the size in WCHAR_Ts and in the ANSI
version it's supposed to be the size in bytes. In both cases it should be
the size in TCHARs. In the ANSI version it would be pretty hard to predict
a size in characters. Now, even though my code commonly specified the
buffer size in known units, was this a common mistake or a common accuracy?

Who is really making mistakes here, and will the mistakes be fixed?

From: Alexander Grigoriev on
I think in this case number of characters means TCHAR's, not number of
codepoints.

"Norman Diamond" <ndiamond(a)community.nospam> wrote in message
news:udOyprwgGHA.1856(a)TK2MSFTNGP03.phx.gbl...
>
> This looks terrible. Actually _snwprintf_s looks mostly OK, since the
> programmer wants to do calculations on the number of wide characters and
> keep track of how much space remains in the buffer. But why does
> _snprintf_s return the number of characters instead of the number of
> bytes?
> If a programmer is using the ANSI version then the programmer wants to do
> calculations on the number of bytes in order to keep track of how much
> space
> remains in the buffer. I also hope that _snwprintf_s doesn't have a split
> personality on the treatment of surrogate pairs.
>


From: John Carson on
"Norman Diamond" <ndiamond(a)community.nospam> wrote in message
news:udOyprwgGHA.1856(a)TK2MSFTNGP03.phx.gbl
>
>The search function of MSDN library United
> States found the page for _snwprintf_s in MSDN library Korea but not
> in MSDN library United States. Some manual searching found it in
> MSDN library United States.
>
> Now for some strange looking statements in page
> http://msdn2.microsoft.com/en-us/library/f30dzcf6.aspx
>
> First are two important statements which are only a bit strange:
>> sizeOfBuffer
>> The size of the storage location for output. Size in bytes for
>> _snprintf_s or size in words for _snwprintf_s.
>> Count
>> Maximum number of characters to store, or _TRUNCATE.
>
> OK, the sizeOfBuffer parameter is the same as the count parameter of
> the old _snwprintf function. This really specifies the size of the
> buffer. The new Count parameter specifies a maximum number of
> characters.

Wrong. The count parameter of the old function is the same as the count
parameter of the new function. The sizeOfBuffer parameter exists in the new
function and has no counterpart in the old.

In both the old and new functions, you use the count parameter to give you
manual control of the number of characters copied for reasons that may or
may not be related to buffer size, e.g., you may only want to copy 3
characters even though the source buffer is a thousand characters long and
the destination buffer could hold a million.

In the case of sprintf and swprintf, there is no count parameter at all.
Likewise, there is no count parameter in the new functions, sprintf_s and
swprintf_s. However, you have a new sizeOfBuffer parameter.

> I suppose the dual limit is a convenience, but I don't
> understand how the level of security improves. The size of the
> buffer is still specified the same way even though the parameter name
> has changed, and the new Count parameter specifies a different
> alternative limit instead of the size of the buffer.

As noted above, the count parameter does not specify the size of the buffer.

Moreover, you are attempting to infer the total properties of the function
from its argument list. The differences go beyond that. In particular,
_snprintf/_snwprintf do not null terminate a string if the length of the
string is >= count, which creates the risk of buffer overruns.

Read the remarks under Return value and other remarks on the page you have
linked to.

>> _snprintf_s returns the number of characters stored in buffer, not
>> counting the terminating null character. _snwprintf_s returns the
>> number of wide characters stored in buffer, not counting the
>> terminating null wide character.
>
> This looks terrible. Actually _snwprintf_s looks mostly OK, since the
> programmer wants to do calculations on the number of wide characters
> and keep track of how much space remains in the buffer. But why does
> _snprintf_s return the number of characters instead of the number of
> bytes?

Um...because a byte and a char have the same size?

> If a programmer is using the ANSI version then the programmer
> wants to do calculations on the number of bytes in order to keep
> track of how much space remains in the buffer. I also hope that
> _snwprintf_s doesn't have a split personality on the treatment of
> surrogate pairs.
>> In C++, using these functions is simplified by template overloads;
>> the overloads can infer buffer length automatically (eliminating the
>> need to specify a size argument) and they can automatically replace
>> older, non-secure functions with their newer, secure counterparts.
>> For more information, see Secure Template Overloads.
>
> I'm not sure how Secure Template Overloads can infer buffer length
> automatically, but maybe they call some undocumented memory management
> functions,

Try this.

#include <iostream>
using namespace std;

template<int n>
void foo(char (&buff)[n])
{
cout << "sizeof buffer is " << n << endl;
}

int main()
{
char buffer[12];
foo(buffer);
}



so OK, I read that page too.
>
> http://msdn2.microsoft.com/en-us/library/ms175759.aspx
>> To enable template overloads for the count functions, define
>> _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT to be 1. Before doing
>> so, however, make sure that your code passes the count of
>> characters, not the size of the buffer (a common mistake).
>
> Um, no wonder it's common for my code to pass the size of the buffer
> instead of the count of characters. Look again at the sizeOfBuffer
> parameter to _sntprintf_s and the count parameter to the old
> _sntprintf function. In the Unicode version it's supposed to be the
> size in WCHAR_Ts and in the ANSI version it's supposed to be the size
> in bytes. In both cases it should be the size in TCHARs.

That is the same thing.


--
John Carson




From: Norman Diamond on
"John Carson" <jcarson_n_o_sp_am_(a)netspace.net.au> wrote in message
news:OmrNmqygGHA.1320(a)TK2MSFTNGP04.phx.gbl...
> "Norman Diamond" <ndiamond(a)community.nospam> wrote in message
> news:udOyprwgGHA.1856(a)TK2MSFTNGP03.phx.gbl
>>
>> Now for some strange looking statements in page
>> http://msdn2.microsoft.com/en-us/library/f30dzcf6.aspx
>>
>> First are two important statements which are only a bit strange:
>>> sizeOfBuffer
>>> The size of the storage location for output. Size in bytes for
>>> _snprintf_s or size in words for _snwprintf_s.
>>> Count
>>> Maximum number of characters to store, or _TRUNCATE.
>>
>> OK, the sizeOfBuffer parameter is the same as the count parameter of the
>> old _snwprintf function. This really specifies the size of the buffer.
>> The new Count parameter specifies a maximum number of characters.
>
> Wrong. The count parameter of the old function is the same as the count
> parameter of the new function. The sizeOfBuffer parameter exists in the
> new function and has no counterpart in the old.

You're right.

http://msdn2.microsoft.com/en-us/library/2ts7cx93.aspx
> count
> Maximum number of characters to store.

For some reason I thought that the old _sntprintf function counted bytes in
the ANSI version but counted WCHAR_Ts in the Unicode version. But here it
is exactly as you said, sitting in front of me and I missed it.

ISO C has a function snprintf which counts bytes (because ISO misspells the
word byte as "character") but ISO C++ doesn't have function snprintf. That
must be the reason why Microsoft has function _snprintf with a leading
underscore, along with _snwprintf and _sntprintf. Since the Microsoft ANSI
version of the underscored function counts actual characters, it really is
lacking in security and the _sntprintf_s family is really needed. Both you
and I detected why the sizeOfBuffer parameter is necessary, but I screwed up
in further analysis. Thank you.

> Moreover, you are attempting to infer the total properties of the function
> from its argument list. The differences go beyond that. In particular,
> _snprintf/_snwprintf do not null terminate a string if the length of the
> string is >= count, which creates the risk of buffer overruns.

Again you are right. The ISO C function snprintf doesn't have this problem,
but again snprintf doesn't exist in ISO C++, and the Microsoft C++ functions
_snprintf/_snwprintf do have this problem.

[MSDN:]
>>> _snprintf_s returns the number of characters stored in buffer, not
>>> counting the terminating null character. _snwprintf_s returns the number
>>> of wide characters stored in buffer, not counting the terminating null
>>> wide character.
>>
>> This looks terrible. Actually _snwprintf_s looks mostly OK, since the
>> programmer wants to do calculations on the number of wide characters and
>> keep track of how much space remains in the buffer. But why does
>> _snprintf_s return the number of characters instead of the number of
>> bytes?
>
> Um...because a byte and a char have the same size?

No. Even though a byte and a char have the same size, a character doesn't.
ISO uses the word "character" more or less interchangeably with byte and
char, but real world programs cannot. In ANSI environments each character
occupies one or two bytes depending on the individual character and the code
page. In UTF16 each character occupies two bytes except for surrogate
pairs.

[MSDN:]
>>> In C++, using these functions is simplified by template overloads; the
>>> overloads can infer buffer length automatically (eliminating the need to
>>> specify a size argument) and they can automatically replace older,
>>> non-secure functions with their newer, secure counterparts. For more
>>> information, see Secure Template Overloads.
>>
>> I'm not sure how Secure Template Overloads can infer buffer length
>> automatically, but maybe they call some undocumented memory management
>> functions,
>
> Try this.
> template<int n>
> void foo(char (&buff)[n])

Try it with a buffer which is allocated dynamically with size large enough
for the data.

>> http://msdn2.microsoft.com/en-us/library/ms175759.aspx
>>> To enable template overloads for the count functions, define
>>> _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT to be 1. Before doing so,
>>> however, make sure that your code passes the count of characters, not
>>> the size of the buffer (a common mistake).
>>
>> Um, no wonder it's common for my code to pass the size of the buffer
>> instead of the count of characters. Look again at the sizeOfBuffer
>> parameter to _sntprintf_s and the count parameter to the old _sntprintf
>> function. In the Unicode version it's supposed to be the size in
>> WCHAR_Ts and in the ANSI version it's supposed to be the size in bytes.
>> In both cases it should be the size in TCHARs.
>
> That is the same thing.

What is the same as what? Again, the count of characters is not the count
of TCHARS (except in the case of a Unicode compilation while ignoring
surrogate pairs). ISO defines "character" differently from Microsoft and an
ISO character cannot store all real characters. But we're discussing MSDN
here not ISO.

From: John Carson on
"Norman Diamond" <ndiamond(a)community.nospam> wrote in message
news:uLGQUd4gGHA.4452(a)TK2MSFTNGP05.phx.gbl
> "John Carson" <jcarson_n_o_sp_am_(a)netspace.net.au> wrote in message
> news:OmrNmqygGHA.1320(a)TK2MSFTNGP04.phx.gbl...
>> "Norman Diamond" <ndiamond(a)community.nospam> wrote in message
>> news:udOyprwgGHA.1856(a)TK2MSFTNGP03.phx.gbl
>>>
>
> ISO C has a function snprintf which counts bytes (because ISO
> misspells the word byte as "character") but ISO C++ doesn't have
> function snprintf.

It would help if you identified what version of ISO C you are referring to.
I presume you mean C99.

> [MSDN:]
>>>> _snprintf_s returns the number of characters stored in buffer, not
>>>> counting the terminating null character. _snwprintf_s returns the
>>>> number of wide characters stored in buffer, not counting the
>>>> terminating null wide character.
>>>
>>> This looks terrible. Actually _snwprintf_s looks mostly OK, since
>>> the programmer wants to do calculations on the number of wide
>>> characters and keep track of how much space remains in the buffer. But
>>> why does _snprintf_s return the number of characters instead of
>>> the number of bytes?
>>
>> Um...because a byte and a char have the same size?
>
> No. Even though a byte and a char have the same size, a character
> doesn't. ISO uses the word "character" more or less interchangeably
> with byte and char, but real world programs cannot. In ANSI
> environments each character occupies one or two bytes depending on
> the individual character and the code page. In UTF16 each character
> occupies two bytes except for surrogate pairs.

I take it you are referring to Microsoft's multibyte characters for Japanese
characters and such. I have never used them myself --- my narrowness was
showing.

I note that sprintf_s is documented to return the number of bytes written.
It would be surprising if sprintf_s and snprintf_s returned different
things, so I suggest you test this to see what is really returned.

If the function does return the number of characters rather than the number
of bytes, then this may not be as inconvenient as it appears. With new
functions such as strcat_s/_mbscat_s, you do not have to tell the function
how much space remains; you only have to tell it the total size of the
buffer.


> [MSDN:]
>>>> In C++, using these functions is simplified by template overloads;
>>>> the overloads can infer buffer length automatically (eliminating
>>>> the need to specify a size argument) and they can automatically
>>>> replace older, non-secure functions with their newer, secure
>>>> counterparts. For more information, see Secure Template Overloads.
>>>
>>> I'm not sure how Secure Template Overloads can infer buffer length
>>> automatically, but maybe they call some undocumented memory
>>> management functions,
>>
>> Try this.
>> template<int n>
>> void foo(char (&buff)[n])
>
> Try it with a buffer which is allocated dynamically with size large
> enough for the data.

Yes, I know it doesn't work with dynamically allocated buffers. Microsoft
says that in the page you link to

>
>>> http://msdn2.microsoft.com/en-us/library/ms175759.aspx

"Note that these template overloads only work for static arrays. Dynamically
allocated buffers require additional source code changes."

I was merely explaining how it can work when it does work.

--
John Carson