summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph M. Becker <cmbecker69@gmx.de>2020-06-29 19:06:56 +0200
committerChristoph M. Becker <cmbecker69@gmx.de>2020-06-29 19:06:56 +0200
commitbf6720d582de512fb6a8dd42c8515bc14e0953c5 (patch)
tree62ef1c490dbe33203d4350cc9978c7abfe50f5c1
parent43b5d5834197bef731a06f8ea025550df08c3fd1 (diff)
parent4af69b84779c1e13e0d98a8eac18a81c0d61f283 (diff)
downloadphp-git-bf6720d582de512fb6a8dd42c8515bc14e0953c5.tar.gz
Merge branch 'PHP-7.4'
* PHP-7.4: Fix #63208: BSTR to PHP string conversion not binary safe
-rw-r--r--ext/com_dotnet/com_olechar.c55
-rw-r--r--ext/com_dotnet/com_variant.c17
-rw-r--r--ext/com_dotnet/php_com_dotnet_internal.h2
-rw-r--r--ext/com_dotnet/tests/bug63208.phpt17
4 files changed, 77 insertions, 14 deletions
diff --git a/ext/com_dotnet/com_olechar.c b/ext/com_dotnet/com_olechar.c
index 7eda51b73b..89aed1e389 100644
--- a/ext/com_dotnet/com_olechar.c
+++ b/ext/com_dotnet/com_olechar.c
@@ -101,3 +101,58 @@ PHP_COM_DOTNET_API char *php_com_olestring_to_string(OLECHAR *olestring, size_t
return string;
}
+
+BSTR php_com_string_to_bstr(zend_string *string, int codepage)
+{
+ BSTR bstr = NULL;
+ DWORD flags = codepage == CP_UTF8 ? 0 : MB_PRECOMPOSED | MB_ERR_INVALID_CHARS;
+ size_t mb_len = ZSTR_LEN(string);
+ int wc_len;
+
+ if ((wc_len = MultiByteToWideChar(codepage, flags, ZSTR_VAL(string), (int)mb_len + 1, NULL, 0)) <= 0) {
+ goto fail;
+ }
+ if ((bstr = SysAllocStringLen(NULL, (UINT)(wc_len - 1))) == NULL) {
+ goto fail;
+ }
+ if ((wc_len = MultiByteToWideChar(codepage, flags, ZSTR_VAL(string), (int)mb_len + 1, bstr, wc_len)) <= 0) {
+ goto fail;
+ }
+ return bstr;
+
+fail:
+ char *msg = php_win32_error_to_msg(GetLastError());
+ php_error_docref(NULL, E_WARNING,
+ "Could not convert string to unicode: `%s'", msg);
+ LocalFree(msg);
+ SysFreeString(bstr);
+ return SysAllocString(L"");
+}
+
+zend_string *php_com_bstr_to_string(BSTR bstr, int codepage)
+{
+ zend_string *string = NULL;
+ UINT wc_len = SysStringLen(bstr);
+ int mb_len;
+
+ mb_len = WideCharToMultiByte(codepage, 0, bstr, wc_len + 1, NULL, 0, NULL, NULL);
+ if (mb_len > 0) {
+ string = zend_string_alloc(mb_len - 1, 0);
+ mb_len = WideCharToMultiByte(codepage, 0, bstr, wc_len + 1, ZSTR_VAL(string), mb_len, NULL, NULL);
+ }
+
+ if (mb_len <= 0) {
+ char *msg = php_win32_error_to_msg(GetLastError());
+
+ php_error_docref(NULL, E_WARNING,
+ "Could not convert string from unicode: `%s'", msg);
+ LocalFree(msg);
+
+ if (string != NULL) {
+ zend_string_release(string);
+ }
+ string = ZSTR_EMPTY_ALLOC();
+ }
+
+ return string;
+}
diff --git a/ext/com_dotnet/com_variant.c b/ext/com_dotnet/com_variant.c
index 72cf16b9e3..83940e93a1 100644
--- a/ext/com_dotnet/com_variant.c
+++ b/ext/com_dotnet/com_variant.c
@@ -94,7 +94,6 @@ bogus:
PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, int codepage)
{
- OLECHAR *olestring;
php_com_dotnet_object *obj;
zend_uchar ztype = IS_NULL;
@@ -162,13 +161,7 @@ PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, int codep
case IS_STRING:
V_VT(v) = VT_BSTR;
- olestring = php_com_string_to_olestring(Z_STRVAL_P(z), Z_STRLEN_P(z), codepage);
- if (CP_UTF8 == codepage) {
- V_BSTR(v) = SysAllocStringByteLen((char*)olestring, (UINT)(wcslen(olestring) * sizeof(OLECHAR)));
- } else {
- V_BSTR(v) = SysAllocStringByteLen((char*)olestring, (UINT)(Z_STRLEN_P(z) * sizeof(OLECHAR)));
- }
- efree(olestring);
+ V_BSTR(v) = php_com_string_to_bstr(Z_STR_P(z), codepage);
break;
case IS_RESOURCE:
@@ -234,12 +227,8 @@ PHP_COM_DOTNET_API int php_com_zval_from_variant(zval *z, VARIANT *v, int codepa
case VT_BSTR:
olestring = V_BSTR(v);
if (olestring) {
- size_t len;
- char *str = php_com_olestring_to_string(olestring,
- &len, codepage);
- ZVAL_STRINGL(z, str, len);
- // TODO: avoid reallocation???
- efree(str);
+ zend_string *str = php_com_bstr_to_string(olestring, codepage);
+ ZVAL_STR(z, str);
olestring = NULL;
}
break;
diff --git a/ext/com_dotnet/php_com_dotnet_internal.h b/ext/com_dotnet/php_com_dotnet_internal.h
index 4974bb78e3..1d089a2ed6 100644
--- a/ext/com_dotnet/php_com_dotnet_internal.h
+++ b/ext/com_dotnet/php_com_dotnet_internal.h
@@ -84,6 +84,8 @@ PHP_COM_DOTNET_API char *php_com_olestring_to_string(OLECHAR *olestring,
size_t *string_len, int codepage);
PHP_COM_DOTNET_API OLECHAR *php_com_string_to_olestring(const char *string,
size_t string_len, int codepage);
+BSTR php_com_string_to_bstr(zend_string *string, int codepage);
+zend_string *php_com_bstr_to_string(BSTR bstr, int codepage);
/* com_com.c */
diff --git a/ext/com_dotnet/tests/bug63208.phpt b/ext/com_dotnet/tests/bug63208.phpt
new file mode 100644
index 0000000000..ae62dbba98
--- /dev/null
+++ b/ext/com_dotnet/tests/bug63208.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #63208 (BSTR to PHP string conversion not binary safe)
+--SKIPIF--
+<?php
+if (!extension_loaded('com_dotnet')) die('skip com_dotnet extension not available');
+?>
+--FILE--
+<?php
+$string = "\u{0905}b\0cd";
+$variant = new VARIANT($string, VT_ARRAY | VT_UI1, CP_UTF8); // Array of bytes
+$converted = (string) $variant;
+var_dump(bin2hex($string));
+var_dump(bin2hex($converted));
+?>
+--EXPECT--
+string(14) "e0a48562006364"
+string(14) "e0a48562006364"