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