On 10/25/2013 03:21 PM, Manlio Perillo wrote:
> Hi.
>
> The question may seems unusual, but I need to make snprintf fail due to
> encoding error in a portable way, to make sure the test suite of a
> library I'm writing has 100% of test coverage.
>
> What is a simple and standard conforming method to make snprintf return a
> negative value?
...
"The snprintf function returns ... a negative value if an encoding error
occurred." (7.21.6.6p3), and that's the only way it can do so.
"An encoding error occurs if the character sequence presented to the
underlying mbrtowc function does not form a valid (generalized)
multibyte character, or if the code value passed to the underlying
wcrtomb does not correspond to a valid (generalized) multibyte
character. The wide character input/output functions and the byte
input/output functions store the value of the macro EILSEQ in errno if
and only if an encoding error occurs." (7.21.3p14)
The phrase "encoding error" is italicized, which is an ISO convention
for indicating that this paragraph defines the meaning of that phrase.
Therefore, in order to trigger an encoding error, you have to using
mbrtowc() or wcrtomb(), directly or indirectly.
You can't figure out what might cause this happen just by looking at the
description of snprintf(). The relevant part of that description says
"The snprintf function is equivalent to fprintf, except ..."
(7.31.6.6p2). You have to look at the description of fprintf(), where
you find that only wcrtomb() is relevant in this case, and only when
using the "%lc" or "%ls" format specifiers. I see from your example code
that you were probably already aware of that fact, but I'm not very
familiar with these parts of the standard, so I had to track things down
systematically.
The behavior of "%lc" is defined in terms of "%ls", so I'll just quote
the description for "%ls":
" ... the argument shall be a pointer to the initial element of an array
of wchar_t type. Wide characters from the array are converted to
multibyte characters (each as if by a call to the wcrtomb function, with
the conversion state described by an mbstate_t object initialized to
zero before the first wide character is converted) ..." (7.21.6.1p8).
Therefore, what you need to do is create a wchar_t array containing a
value that does not correspond to a valid generalized multibyte
character. Which values have that property is implementation specific.
The most portable way to identify such a value is to loop over all
possibilities from WCHAR_MIN to WCHAR_MAX, passing each one to wcrtomb()
until it returns a negative value. There need not be any such value.