Older Windows versions do not support CP_UTF8 code page and
MB_ERR_INVALID_CHARS flag and signal ERROR_INVALID_PARAMETER
or ERROR_INVALID_FLAGS error.

Properly check for any failure from MultiByteToWideChar() and
WideCharToMultiByte() calls and return error back to the caller.
---
 mingw-w64-crt/misc/mingw_mbwc_convert.c | 65 +++++++++++++++++++++++--
 1 file changed, 61 insertions(+), 4 deletions(-)

diff --git a/mingw-w64-crt/misc/mingw_mbwc_convert.c 
b/mingw-w64-crt/misc/mingw_mbwc_convert.c
index dc00589b3322..90f7a36adade 100644
--- a/mingw-w64-crt/misc/mingw_mbwc_convert.c
+++ b/mingw-w64-crt/misc/mingw_mbwc_convert.c
@@ -1,21 +1,50 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <wchar.h>
+#include <errno.h>
 #include <windows.h>
 #include <winnls.h>
 
 int __cdecl __mingw_str_wide_utf8(const wchar_t * const wptr, char **mbptr, 
size_t *buflen)
 {
-  size_t len;
+  int len;
   char *buf;
   int ret = 0;
 
   len = WideCharToMultiByte(CP_UTF8, 0, wptr, -1, NULL, 0, NULL, NULL); /* Get 
utf-8 string length */
+  if (len <= 0) {
+    switch (GetLastError()) {
+      case ERROR_INVALID_PARAMETER: /* CP_UTF8 is not supported */
+      case ERROR_INVALID_FLAGS: /* CP_UTF8 is not supported */
+        errno = ENOSYS;
+        *mbptr = NULL;
+        if (buflen != NULL) *buflen = 0;
+        return 0;
+      case NO_ERROR:
+        if (len == 0)
+          break;
+        /* fallthrough */
+      default:
+        errno = EINVAL;
+        *mbptr = NULL;
+        if (buflen != NULL) *buflen = 0;
+        return 0;
+    }
+  }
   buf = calloc(len + 1, sizeof (char)); /* Can we assume sizeof char always = 
1? */
 
   if(!buf) len = 0;
   else {
-    if (len != 0) ret = WideCharToMultiByte(CP_UTF8, 0, wptr, -1, buf, len, 
NULL, NULL); /*Do actual conversion*/
+    if (len != 0) {
+      ret = WideCharToMultiByte(CP_UTF8, 0, wptr, -1, buf, len, NULL, NULL); 
/*Do actual conversion*/
+      if (ret < 0 || (ret == 0 && GetLastError() != NO_ERROR)) {
+        free(buf);
+        errno = EINVAL;
+        *mbptr = NULL;
+        if (buflen != NULL) *buflen = 0;
+        return 0;
+      }
+    }
     buf[len] = '\0'; /* Must terminate */
   }
   *mbptr = buf; /* Set string pointer to allocated buffer */
@@ -25,16 +54,44 @@ int __cdecl __mingw_str_wide_utf8(const wchar_t * const 
wptr, char **mbptr, size
 
 int __cdecl __mingw_str_utf8_wide(const char *const mbptr, wchar_t **wptr, 
size_t *buflen)
 {
-  size_t len;
+  int len;
   wchar_t *buf;
   int ret = 0;
 
   len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, mbptr, -1, NULL, 
0); /* Get converted size */
+  if (len <= 0) {
+    switch (GetLastError()) {
+      case ERROR_INVALID_PARAMETER: /* CP_UTF8 or MB_ERR_INVALID_CHARS is not 
supported */
+      case ERROR_INVALID_FLAGS: /* CP_UTF8 or MB_ERR_INVALID_CHARS is not 
supported */
+        errno = ENOSYS;
+        *wptr = NULL;
+        if (buflen != NULL) *buflen = 0;
+        return 0;
+      case NO_ERROR:
+        if (len == 0)
+          break;
+        /* fallthrough */
+      default:
+        errno = EINVAL;
+        *wptr = NULL;
+        if (buflen != NULL) *buflen = 0;
+        return 0;
+    }
+  }
   buf = calloc(len + 1, sizeof (wchar_t)); /* Allocate memory accordingly */
 
   if(!buf) len = 0;
   else {
-    if (len != 0) ret = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, 
mbptr, -1, buf, len); /* Do conversion */
+    if (len != 0) {
+      ret = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, mbptr, -1, 
buf, len); /* Do conversion */
+      if (ret < 0 || (ret == 0 && GetLastError() != NO_ERROR)) {
+        free(buf);
+        errno = EINVAL;
+        *wptr = NULL;
+        if (buflen != NULL) *buflen = 0;
+        return 0;
+      }
+    }
     buf[len] = L'\0'; /* Must terminate */
   }
   *wptr = buf; /* Set string pointer to allocated buffer */
-- 
2.20.1



_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to