Better fix for snprintf non-termination on windows.

Replaces https://codereview.chromium.org/1062983002/
BUG=469244
R=brucedawson@chromium.org

Review URL: https://codereview.chromium.org/1077903002
diff --git a/core/include/fxcrt/fx_system.h b/core/include/fxcrt/fx_system.h
index a875da5..d030bf7 100644
--- a/core/include/fxcrt/fx_system.h
+++ b/core/include/fxcrt/fx_system.h
@@ -34,8 +34,9 @@
 #endif
 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
 #define _CRT_SECURE_NO_WARNINGS
+#include <sal.h>
 #include <windows.h>
-#endif
+#endif  // _FXM_PLATFORM_WINDOWS_
 #define _FX_W32_		1
 #define _FX_W64_		2
 #ifndef _FX_WORDSIZE_
@@ -137,13 +138,18 @@
 #define FX_MAX(a, b) (((a) > (b)) ? (a) : (b))
 #define FX_MIN(a, b) (((a) < (b)) ? (a) : (b))
 #define FX_PI	3.1415926535897932384626433832795f
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
-#define FXSYS_snprintf	_snprintf
-#define FXSYS_vsnprintf	_vsnprintf
+
+// NOTE: prevent use of the return value from snprintf() since some platforms
+// have different return values (e.g. windows _vsnprintf()), and provide
+// versions that always NUL-terminate.
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ && _MSC_VER < 1900
+void FXSYS_snprintf(char *str, size_t size, _Printf_format_string_ const char* fmt, ...);
+void FXSYS_vsnprintf(char *str, size_t size, const char* fmt, va_list ap);
 #else
-#define FXSYS_snprintf	snprintf
-#define FXSYS_vsnprintf	vsnprintf
+#define FXSYS_snprintf	(void) snprintf
+#define FXSYS_vsnprintf	(void) vsnprintf
 #endif
+
 #define FXSYS_sprintf	DO_NOT_USE_SPRINTF_DIE_DIE_DIE
 #define FXSYS_vsprintf	DO_NOT_USE_VSPRINTF_DIE_DIE_DIE
 #define FXSYS_strchr	strchr
diff --git a/core/src/fxcrt/fx_basic_util.cpp b/core/src/fxcrt/fx_basic_util.cpp
index 5a40c2b..c3df07f 100644
--- a/core/src/fxcrt/fx_basic_util.cpp
+++ b/core/src/fxcrt/fx_basic_util.cpp
@@ -169,6 +169,24 @@
     }
     return bNegative ? -value : value;
 }
+
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ && _MSC_VER < 1900
+void FXSYS_snprintf(char *str, size_t size, _Printf_format_string_ const char* fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    FXSYS_vsnprintf(str, size, fmt, ap);
+    va_end(ap);
+}
+void FXSYS_vsnprintf(char *str, size_t size, const char* fmt, va_list ap)
+{
+    (void) _vsnprintf(str, size, fmt, ap);
+    if (size) {
+        str[size - 1] = 0;
+    }
+}
+#endif  // _FXM_PLATFORM_WINDOWS_ && _MSC_VER < 1900
+
 static FX_BOOL FX_IsDigit(FX_BYTE ch)
 {
     return (ch >= '0' && ch <= '9') ? TRUE : FALSE;
diff --git a/core/src/fxcrt/fx_basic_wstring.cpp b/core/src/fxcrt/fx_basic_wstring.cpp
index ce6a1cd..dfdbef8 100644
--- a/core/src/fxcrt/fx_basic_wstring.cpp
+++ b/core/src/fxcrt/fx_basic_wstring.cpp
@@ -976,9 +976,9 @@
                         nItemLen = nPrecision + nWidth + 128;
                     } else {
                         double f;
-                        char pszTemp[256] = {0};
+                        char pszTemp[256];
                         f = va_arg(argList, double);
-                        FXSYS_snprintf(pszTemp, sizeof(pszTemp) - 1, "%*.*f", nWidth, nPrecision + 6, f );
+                        FXSYS_snprintf(pszTemp, sizeof(pszTemp), "%*.*f", nWidth, nPrecision + 6, f );
                         nItemLen = (FX_STRSIZE)FXSYS_strlen(pszTemp);
                     }
                     break;