mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Fix #63208: BSTR to PHP string conversion not binary safe
A `BSTR` is similar to a `zend_string`; it stores the length of the string just before the actual string, and thus the string may contain NUL bytes. However, `php_com_olestring_to_string()` is supposed to deal with arbitrary `OLECHAR*`s which may not be `BSTR`s, so we introduce `php_com_bstr_to_string()` and use it for the only case where we actually have to deal with `BSTR`s which may contain NUL bytes. Contrary to `php_com_olestring_to_string()` we return a `zend_string`, so we can save the re-allocation when converting to a `zval`. We also cater to `php_com_string_to_olestring()` not being binary safe, with basically the same fix we did for `php_com_olestring_to_string()`.
This commit is contained in:
parent
816b4c1235
commit
a385cfa7ad
5 changed files with 80 additions and 14 deletions
3
NEWS
3
NEWS
|
@ -6,6 +6,9 @@ PHP NEWS
|
||||||
. Fixed bug #79030 (Upgrade apache2handler's php_apache_sapi_get_request_time
|
. Fixed bug #79030 (Upgrade apache2handler's php_apache_sapi_get_request_time
|
||||||
to return usec). (Herbert256)
|
to return usec). (Herbert256)
|
||||||
|
|
||||||
|
- COM:
|
||||||
|
. Fixed bug #63208 (BSTR to PHP string conversion not binary safe). (cmb)
|
||||||
|
|
||||||
- Curl:
|
- Curl:
|
||||||
. Fixed bug #79741 (curl_setopt CURLOPT_POSTFIELDS asserts on object with
|
. Fixed bug #79741 (curl_setopt CURLOPT_POSTFIELDS asserts on object with
|
||||||
declared properties). (Nikita)
|
declared properties). (Nikita)
|
||||||
|
|
|
@ -103,3 +103,58 @@ PHP_COM_DOTNET_API char *php_com_olestring_to_string(OLECHAR *olestring, size_t
|
||||||
|
|
||||||
return string;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -96,7 +96,6 @@ bogus:
|
||||||
|
|
||||||
PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, int codepage)
|
PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, int codepage)
|
||||||
{
|
{
|
||||||
OLECHAR *olestring;
|
|
||||||
php_com_dotnet_object *obj;
|
php_com_dotnet_object *obj;
|
||||||
zend_uchar ztype = IS_NULL;
|
zend_uchar ztype = IS_NULL;
|
||||||
|
|
||||||
|
@ -164,13 +163,7 @@ PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, int codep
|
||||||
|
|
||||||
case IS_STRING:
|
case IS_STRING:
|
||||||
V_VT(v) = VT_BSTR;
|
V_VT(v) = VT_BSTR;
|
||||||
olestring = php_com_string_to_olestring(Z_STRVAL_P(z), Z_STRLEN_P(z), codepage);
|
V_BSTR(v) = php_com_string_to_bstr(Z_STR_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);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_RESOURCE:
|
case IS_RESOURCE:
|
||||||
|
@ -236,12 +229,8 @@ PHP_COM_DOTNET_API int php_com_zval_from_variant(zval *z, VARIANT *v, int codepa
|
||||||
case VT_BSTR:
|
case VT_BSTR:
|
||||||
olestring = V_BSTR(v);
|
olestring = V_BSTR(v);
|
||||||
if (olestring) {
|
if (olestring) {
|
||||||
size_t len;
|
zend_string *str = php_com_bstr_to_string(olestring, codepage);
|
||||||
char *str = php_com_olestring_to_string(olestring,
|
ZVAL_STR(z, str);
|
||||||
&len, codepage);
|
|
||||||
ZVAL_STRINGL(z, str, len);
|
|
||||||
// TODO: avoid reallocation???
|
|
||||||
efree(str);
|
|
||||||
olestring = NULL;
|
olestring = NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -89,6 +89,8 @@ PHP_COM_DOTNET_API char *php_com_olestring_to_string(OLECHAR *olestring,
|
||||||
size_t *string_len, int codepage);
|
size_t *string_len, int codepage);
|
||||||
PHP_COM_DOTNET_API OLECHAR *php_com_string_to_olestring(char *string,
|
PHP_COM_DOTNET_API OLECHAR *php_com_string_to_olestring(char *string,
|
||||||
size_t string_len, int codepage);
|
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 */
|
/* com_com.c */
|
||||||
|
|
17
ext/com_dotnet/tests/bug63208.phpt
Normal file
17
ext/com_dotnet/tests/bug63208.phpt
Normal file
|
@ -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"
|
Loading…
Add table
Add a link
Reference in a new issue