Sorry, I didn't see your message as it was sent to wine-patches.
On Thursday, 18 Dec 2014 18:09:01 +0100, Jonathan Vollebregt wrote:
If buffer or format is NULL, or if count is less than or equal to zero, these functions invoke the invalid parameter handler, as described in Parameter Validation. If execution is allowed to continue, these functions return -1 and set errno to EINVAL.
This doc says that vsnprintf *should* always return -1 given your example.
Yes, MSDN does say that.
Is there a test that shows the MSDN docs are wrong?
I'm not sure if Wine has one, but I'll check. Running multiple tests with Visual Studio 2013 on Windows 7 64-bit returns the number of chars that would be written for vsnprintf(NULL, 0, fmt, args).
-1 is returned in cases when "the number of characters to write is greater than count". So some examples would be vsnprintf(valid buffer, 0, fmt, args) or vsnprintf(very small buffer, 8, fmt, args).
On 12/18/2014 11:57 AM, Hugh McMaster wrote:
Recent discussions on the wine-devel mailing list conclude that Wine's vsnprintfW must duplicate Windows' vsnprintf behaviourW[1].
Currently, there are two issues.
vsnprintfW(NULL, 0, fmt, args). Both Windows and GCC allow these arguments. Both return the number of chars that would be written in this instance. Wine returns -1, which is incorrect.
vsnprintfW(some buffer, 0, fmt, args). Both Windows and Wine return -1, but in this case, Wine does this by default. We need to maintain this behaviour.
To fix these inconsistencies, we need to add an 'else' block to the check for len (i.e. checking for a non-zero value). Then we check for a NULL pointer. If true, we return (int)written, like Windows and GCC do, because vsnprintfW(NULL, 0, fmt, args) was called.
This patch fixes these issues.
[1] https://www.winehq.org/pipermail/wine-devel/2014-December/106066.html
On 12/19/2014 03:35 AM, Hugh McMaster wrote:
On Thursday, 18 Dec 2014 18:09:01 +0100, Jonathan Vollebregt wrote:
Is there a test that shows the MSDN docs are wrong?
I'm not sure if Wine has one, but I'll check. Running multiple tests with Visual Studio 2013 on Windows 7 64-bit returns the number of chars that would be written for vsnprintf(NULL, 0, fmt, args).
-1 is returned in cases when "the number of characters to write is greater than count". So some examples would be vsnprintf(valid buffer, 0, fmt, args) or vsnprintf(very small buffer, 8, fmt, args).
Special-casing buff=NULL size=0 sounds like MS's attempt to add a bit more C99 compliance to the (v)snprintf functions, in addition to adding more C99 functions in general, which they've been talking about the last couple of years. This behavior may be different from older pre-VS2013 versions.
On Friday, 19 Dec 2014 06:45:57 -0800, Chris Robinson wrote:
Special-casing buff=NULL size=0 sounds like MS's attempt to add a bit more C99 compliance to the (v)snprintf functions, in addition to adding more C99 functions in general, which they've been talking about the last couple of years. This behavior may be different from older pre-VS2013 versions.
I ran the same tests earlier today using VS2008 and VS2010, and I got the same results. Both vsnprintf and _vsnwprintf behave the same way.
I added two tests to dlls/msvcrt/tests/printf.c (not sure if that was the correct place) and submitted the diff to the testbot.
[1] https://testbot.winehq.org/JobDetails.pl?Key=10842 [2] https://testbot.winehq.org/JobDetails.pl?Key=10843
The tests pass on all VMs, except for W2000. That OS fails when calling vsnprintf(NULL, 0, fmt, args).
ret = _vsnwprintf_wrapper( NULL, 0, format, one, two, three ); ok( ret == 11, "got %d, expected 11\n", ret );
What's the best way to handle the different return value in Wine tests?
ok( ret == 11 || ret == -1, "got %d, expected 11\n", ret );
broken() only returns true if the test passes on windows so something like this:
ok(ret == 11 || broken(ret == -1 /* Win2k */), "got %d\n", ret);
Will still fail properly if it returns -1 in wine
On 12/20/2014 12:09 PM, Hugh McMaster wrote:
What's the best way to handle the different return value in Wine tests?
ok( ret == 11 || ret == -1, "got %d, expected 11\n", ret );