Bug 140917 - Windows return -1 when calling vsnprintf with arguments that exceed target buffer size
Summary: Windows return -1 when calling vsnprintf with arguments that exceed target bu...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Web Template Framework (show other bugs)
Version: 528+ (Nightly build)
Hardware: PC Windows 7
: P2 Normal
Assignee: Nobody
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2015-01-26 19:05 PST by Namhoon Kim
Modified: 2015-01-30 05:22 PST (History)
5 users (show)

See Also:


Attachments
Patch (2.37 KB, patch)
2015-01-26 22:31 PST, Namhoon Kim
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Namhoon Kim 2015-01-26 19:05:38 PST
According to https://msdn.microsoft.com/en-us/library/1kt27hek.aspx windows return -1 when calling vsnprintf with arguments that exceed target buffer size.

e.g.)

   char buf[5];
   int return = vsnprintf(buf, 5, "%s", "0123456789");

This API return -1 while other platforms (linux, bsd) return 10 instead. Other platform's reference can be found below.

bsd - https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/vsnprintf.3.html
linux - http://man7.org/linux/man-pages/man3/vsnprintf.3.html

I found this bug while testing JSC::Profiler::Database which announced in https://docs.google.com/document/d/18MQU5Dm31g4cVweuQuGofQAxfbenAAsE_njeTUuKOVA/edit from windows platform. Current WebKit's vsnprintf use looks safe to not overflow the buffer. But when this profiler tries to dump its source code by using WTF::StringPrintStream::toCString(), windows' vsnprintf's -1 return value eventually *broke* WTF::StringPrintStream::vprintf() function's buffer grow logic. Since WTF::StringPrintStream::toCString() buffer grow logic depends to other (linux, bsd) platform's vsnprintf behavior, we need to fix return value of wtf_vsnprintf (which is windows' polyfill of vsnprintf) to same as other platform.
Comment 1 Namhoon Kim 2015-01-26 19:06:35 PST
I'll submit a patch also.
Comment 2 Namhoon Kim 2015-01-26 22:31:33 PST
Created attachment 245424 [details]
Patch
Comment 3 Brent Fulgham 2015-01-27 18:09:57 PST
Comment on attachment 245424 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=245424&action=review

Thank you for noticing this! I had to do some reading just now to understand your change.

> Source/WTF/wtf/StringExtras.h:65
> +        result = _vscprintf(format, args);

I see; MSVC returns negative in the case of a 'buffer overrun converted to a truncation', while POSIX systems return the count as if nothing bad happened.

Very nice fix!
Comment 4 Brent Fulgham 2015-01-27 18:10:38 PST
Thank you for tracking this down. Do we have any other cases where a similar mistake is being made?
Comment 5 Brent Fulgham 2015-01-27 18:13:38 PST
Comment on attachment 245424 [details]
Patch

Looking over this file, it seems like our 'snprintf' (a few lines above) suffers from the exact same problem. Could you please make the same correction there? Then we can land the patch in one go.

r- to request the additional fix be done for 'snprintf'. Otherwise, this looks great!
Comment 6 Namhoon Kim 2015-01-27 18:39:02 PST
> Thank you for tracking this down. Do we have any other cases where a similar mistake is being made?

MSVC version of vprintf_stderr_common (in Assertions.cpp) has similar (or worse) problem. If result debug formatted string length is exactly 1024 bytes, there is no null character placed in the buffer. It results following OutputDebugStringA call prints some garbage bytes also.

I think we simply fix it by calling vsnprintf (which is polyfilled by wtf_vsnprintf when using windows) instead of _vsnprintf.
Comment 7 Namhoon Kim 2015-01-27 18:43:56 PST
> Looking over this file, it seems like our 'snprintf' (a few lines above) suffers from the exact same problem. Could you please make the same correction there? Then we can land the patch in one go.

I fixed it too. Correcting handled before va_end calling. See below hunk please.

 inline int snprintf(char* buffer, size_t count, const char* format, ...) 
 {
     int result;
     va_list args;
     va_start(args, format);
     result = _vsnprintf(buffer, count, format, args);
+    if (result < 0 && errno != EINVAL)
+        result = _vscprintf(format, args);
     va_end(args);
Comment 8 Brent Fulgham 2015-01-28 10:06:26 PST
(In reply to comment #7)
> > Looking over this file, it seems like our 'snprintf' (a few lines above) suffers from the exact same problem. Could you please make the same correction there? Then we can land the patch in one go.
> 
> I fixed it too. Correcting handled before va_end calling. See below hunk
> please.
> 
>  inline int snprintf(char* buffer, size_t count, const char* format, ...) 
>  {
>      int result;
>      va_list args;
>      va_start(args, format);
>      result = _vsnprintf(buffer, count, format, args);
> +    if (result < 0 && errno != EINVAL)
> +        result = _vscprintf(format, args);
>      va_end(args);

Were you planning up submitting an updated patch? Let me know and I'll try to get this in as soon as you have an update.
Comment 9 Brent Fulgham 2015-01-28 12:49:48 PST
This bug could have the following impacts:

1. Our NSAPI plugin tests.
2. Tests involving EditingDelegate dump() operations.
3. Stuff passing through JSC's globalFuncEscape method.
4. JSC date functions (dateProtoFuncToISOString)
5. XML Document parser
6. Windows clipboard utilities.
7. TextStream/TextCodec clients

It will be interesting to see if any of the Windows JSC Date tests start working once this fix is in place.
Comment 10 Radar WebKit Bug Importer 2015-01-28 12:51:25 PST
<rdar://problem/19635602>
Comment 11 Namhoon Kim 2015-01-28 17:41:57 PST
(In reply to comment #8)
> (In reply to comment #7)
> > > Looking over this file, it seems like our 'snprintf' (a few lines above) suffers from the exact same problem. Could you please make the same correction there? Then we can land the patch in one go.
> > 
> > I fixed it too. Correcting handled before va_end calling. See below hunk
> > please.
> > 
> >  inline int snprintf(char* buffer, size_t count, const char* format, ...) 
> >  {
> >      int result;
> >      va_list args;
> >      va_start(args, format);
> >      result = _vsnprintf(buffer, count, format, args);
> > +    if (result < 0 && errno != EINVAL)
> > +        result = _vscprintf(format, args);
> >      va_end(args);
> 
> Were you planning up submitting an updated patch? Let me know and I'll try
> to get this in as soon as you have an update.

What I mean is, that hunk already in the patch I submitted. https://bugs.webkit.org/attachment.cgi?id=245424&action=diff

If I miss understand something on this context, please let me know.
Comment 12 Brent Fulgham 2015-01-28 17:46:56 PST
(In reply to comment #11)
> What I mean is, that hunk already in the patch I submitted.
> https://bugs.webkit.org/attachment.cgi?id=245424&action=diff
> 
> If I miss understand something on this context, please let me know.

Ah! you are right. Sorry!

But I also though you mentioned that something about a similar error in Assertions.cpp that needed correcting?
Comment 13 Brent Fulgham 2015-01-28 17:49:57 PST
Comment on attachment 245424 [details]
Patch

r=me. We can deal with the Assertions.cpp change elsewhere.
Comment 14 Brent Fulgham 2015-01-28 17:50:35 PST
I'll land this as-is. Could you please also package the Assertion.cpp change you mentioned as a separate bug and we'll get that landed, too!
Comment 15 WebKit Commit Bot 2015-01-28 18:32:19 PST
Comment on attachment 245424 [details]
Patch

Clearing flags on attachment: 245424

Committed r179325: <http://trac.webkit.org/changeset/179325>
Comment 16 WebKit Commit Bot 2015-01-28 18:32:23 PST
All reviewed patches have been landed.  Closing bug.
Comment 17 Namhoon Kim 2015-01-29 01:34:30 PST
(In reply to comment #14)
> I'll land this as-is. Could you please also package the Assertion.cpp change
> you mentioned as a separate bug and we'll get that landed, too!

Thank you. I'll pile a bug for that. And I'll check related bugs you linked also.
Comment 18 Brent Fulgham 2015-01-29 09:06:07 PST
(In reply to comment #9)
> This bug could have the following impacts:
> 
> 1. Our NSAPI plugin tests.
> 2. Tests involving EditingDelegate dump() operations.
> 3. Stuff passing through JSC's globalFuncEscape method.
> 4. JSC date functions (dateProtoFuncToISOString)
> 5. XML Document parser
> 6. Windows clipboard utilities.
> 7. TextStream/TextCodec clients
> 
> It will be interesting to see if any of the Windows JSC Date tests start
> working once this fix is in place.

I reran the JSC date function tests, but unfortunately did not see any progressions after applying this patch. Furthermore, the main test units have not shown any new progressions since this change.

So, this is a very useful fix but I don't think our test infrastructure was triggering any bad behavior due to this problem.