mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Fix GH-8750: Can not create VT_ERROR variant type
We add support for creating `VT_ERROR` variants via `__construct()`, and allow casting to int via `variant_cast()` and `variant_set_type()`. We do not, however, allow type conversion by other means, to avoid otherwise easily introduced type confusion. VB(A) also only allows explicit type conversion. We also introduce `DISP_E_PARAMNOTFOUND` which might be the most important `scode` for this purpose, since this allows to skip optional parameters in method calls. Closes GH-8886.
This commit is contained in:
3
NEWS
3
NEWS
@@ -10,6 +10,9 @@ PHP NEWS
|
||||
json_encode(), serialize(), iconv_*(), mb_ereg*(), session_create_id(),
|
||||
http_build_query(), strstr(), Reflection*::__toString(). (Arnaud)
|
||||
|
||||
- COM:
|
||||
. Fixed bug GH-8750 (Can not create VT_ERROR variant type). (cmb)
|
||||
|
||||
- FPM:
|
||||
. Added listen.setfib pool option to set route FIB on FreeBSD. (David Carlier)
|
||||
. Added access.suppress_path pool option to filter access log entries.
|
||||
|
||||
@@ -264,6 +264,7 @@ PHP 8.2 UPGRADE NOTES
|
||||
========================================
|
||||
|
||||
- COM_DOTNET:
|
||||
. DISP_E_PARAMNOTFOUND
|
||||
. LOCALE_NEUTRAL
|
||||
|
||||
- Curl:
|
||||
|
||||
@@ -32,11 +32,13 @@
|
||||
#define PHP_DISP_E_DIVBYZERO ((zend_long) (ULONG) DISP_E_DIVBYZERO)
|
||||
#define PHP_DISP_E_OVERFLOW ((zend_long) (ULONG) DISP_E_OVERFLOW)
|
||||
#define PHP_DISP_E_BADINDEX ((zend_long) (ULONG) DISP_E_BADINDEX)
|
||||
#define PHP_DISP_E_PARAMNOTFOUND ((zend_long) (ULONG) DISP_E_PARAMNOTFOUND)
|
||||
#define PHP_MK_E_UNAVAILABLE ((zend_long) (ULONG) MK_E_UNAVAILABLE)
|
||||
#else
|
||||
#define PHP_DISP_E_DIVBYZERO DISP_E_DIVBYZERO
|
||||
#define PHP_DISP_E_OVERFLOW DISP_E_OVERFLOW
|
||||
#define PHP_DISP_E_BADINDEX DISP_E_BADINDEX
|
||||
#define PHP_DISP_E_PARAMNOTFOUND DISP_E_PARAMNOTFOUND
|
||||
#define PHP_MK_E_UNAVAILABLE MK_E_UNAVAILABLE
|
||||
#endif
|
||||
|
||||
|
||||
@@ -264,6 +264,11 @@ const DISP_E_OVERFLOW = UNKNOWN;
|
||||
* @cname PHP_DISP_E_BADINDEX
|
||||
*/
|
||||
const DISP_E_BADINDEX = UNKNOWN;
|
||||
/**
|
||||
* @var int
|
||||
* @cname PHP_DISP_E_PARAMNOTFOUND
|
||||
*/
|
||||
const DISP_E_PARAMNOTFOUND = UNKNOWN;
|
||||
/**
|
||||
* @var int
|
||||
* @cname PHP_MK_E_UNAVAILABLE
|
||||
|
||||
3
ext/com_dotnet/com_extension_arginfo.h
generated
3
ext/com_dotnet/com_extension_arginfo.h
generated
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 76bd9190ad3f5e8fc3f6d6e0b5561f935c73efd3 */
|
||||
* Stub hash: 3e9f5b80bee0ee6bad7185d0d583858bc8a54dde */
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_variant_set, 0, 2, IS_VOID, 0)
|
||||
ZEND_ARG_OBJ_INFO(0, variant, variant, 0)
|
||||
@@ -292,6 +292,7 @@ static void register_com_extension_symbols(int module_number)
|
||||
REGISTER_LONG_CONSTANT("DISP_E_DIVBYZERO", PHP_DISP_E_DIVBYZERO, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("DISP_E_OVERFLOW", PHP_DISP_E_OVERFLOW, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("DISP_E_BADINDEX", PHP_DISP_E_BADINDEX, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("DISP_E_PARAMNOTFOUND", PHP_DISP_E_PARAMNOTFOUND, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("MK_E_UNAVAILABLE", PHP_MK_E_UNAVAILABLE, CONST_CS | CONST_PERSISTENT);
|
||||
#if SIZEOF_ZEND_LONG == 8
|
||||
REGISTER_LONG_CONSTANT("VT_UI8", VT_UI8, CONST_CS | CONST_PERSISTENT);
|
||||
|
||||
@@ -92,7 +92,7 @@ bogus:
|
||||
}
|
||||
}
|
||||
|
||||
PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, int codepage)
|
||||
static void php_com_variant_from_zval_ex(VARIANT *v, zval *z, int codepage, VARTYPE vt)
|
||||
{
|
||||
php_com_dotnet_object *obj;
|
||||
zend_uchar ztype = IS_NULL;
|
||||
@@ -145,6 +145,11 @@ PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, int codep
|
||||
break;
|
||||
|
||||
case IS_LONG:
|
||||
if (vt == VT_ERROR) {
|
||||
V_VT(v) = VT_ERROR;
|
||||
V_ERROR(v) = Z_LVAL_P(z);
|
||||
break;
|
||||
}
|
||||
#if SIZEOF_ZEND_LONG == 4
|
||||
V_VT(v) = VT_I4;
|
||||
V_I4(v) = Z_LVAL_P(z);
|
||||
@@ -172,6 +177,11 @@ PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, int codep
|
||||
}
|
||||
}
|
||||
|
||||
PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, int codepage)
|
||||
{
|
||||
php_com_variant_from_zval_ex(v, z, codepage, VT_EMPTY);
|
||||
}
|
||||
|
||||
PHP_COM_DOTNET_API zend_result php_com_zval_from_variant(zval *z, VARIANT *v, int codepage)
|
||||
{
|
||||
OLECHAR *olestring = NULL;
|
||||
@@ -448,7 +458,7 @@ PHP_METHOD(variant, __construct)
|
||||
}
|
||||
|
||||
if (zvalue) {
|
||||
php_com_variant_from_zval(&obj->v, zvalue, obj->code_page);
|
||||
php_com_variant_from_zval_ex(&obj->v, zvalue, obj->code_page, vt);
|
||||
}
|
||||
|
||||
/* Only perform conversion if variant not already of type passed */
|
||||
@@ -1019,6 +1029,7 @@ PHP_FUNCTION(variant_set_type)
|
||||
zval *zobj;
|
||||
php_com_dotnet_object *obj;
|
||||
/* VARTYPE == unsigned short */ zend_long vt;
|
||||
VARIANT vtmp;
|
||||
HRESULT res;
|
||||
|
||||
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(),
|
||||
@@ -1027,7 +1038,12 @@ PHP_FUNCTION(variant_set_type)
|
||||
}
|
||||
obj = CDNO_FETCH(zobj);
|
||||
|
||||
res = VariantChangeType(&obj->v, &obj->v, 0, (VARTYPE)vt);
|
||||
if (V_VT(&obj->v) == VT_ERROR) {
|
||||
VariantInit(&vtmp);
|
||||
V_VT(&vtmp) = VT_I4;
|
||||
V_I4(&vtmp) = V_ERROR(&obj->v);
|
||||
}
|
||||
res = VariantChangeType(&obj->v, V_VT(&obj->v) != VT_ERROR ? &obj->v : &vtmp, 0, (VARTYPE)vt);
|
||||
|
||||
if (SUCCEEDED(res)) {
|
||||
if (vt != VT_DISPATCH && obj->typeinfo) {
|
||||
@@ -1063,7 +1079,11 @@ PHP_FUNCTION(variant_cast)
|
||||
obj = CDNO_FETCH(zobj);
|
||||
|
||||
VariantInit(&vres);
|
||||
res = VariantChangeType(&vres, &obj->v, 0, (VARTYPE)vt);
|
||||
if (V_VT(&obj->v) == VT_ERROR) {
|
||||
V_VT(&vres) = VT_I4;
|
||||
V_I4(&vres) = V_ERROR(&obj->v);
|
||||
}
|
||||
res = VariantChangeType(&vres, V_VT(&vres) == VT_EMPTY ? &obj->v : &vres, 0, (VARTYPE)vt);
|
||||
|
||||
if (SUCCEEDED(res)) {
|
||||
php_com_wrap_variant(return_value, &vres, obj->code_page);
|
||||
|
||||
47
ext/com_dotnet/tests/gh8750.phpt
Normal file
47
ext/com_dotnet/tests/gh8750.phpt
Normal file
@@ -0,0 +1,47 @@
|
||||
--TEST--
|
||||
Bug GH-8750 (Can not create VT_ERROR variant type)
|
||||
--EXTENSIONS--
|
||||
com_dotnet
|
||||
--SKIPIF--
|
||||
<?php
|
||||
$provider = "Microsoft.ACE.OLEDB.12.0";
|
||||
$filename = __DIR__ . "\\gh8750.mdb";
|
||||
$catalog = new com("ADOX.Catalog");
|
||||
try {
|
||||
$catalog->Create("Provider=$provider;Data Source=$filename");
|
||||
} catch (com_exception) {
|
||||
die("skip $provider provider not available");
|
||||
}
|
||||
$catalog = null;
|
||||
@unlink($filename);
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
$filename = __DIR__ . "\\gh8750.mdb";
|
||||
|
||||
$catalog = new com("ADOX.Catalog");
|
||||
$catalog->Create("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=$filename");
|
||||
$catalog = null;
|
||||
|
||||
$db = new com("ADODB.Connection");
|
||||
$db->ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=$filename";
|
||||
$db->Mode = 1; // adModeRead
|
||||
$db->Open();
|
||||
// adSchemaProviderSpecific, *missing*, JET_SCHEMA_USERROSTER
|
||||
$rs = $db->OpenSchema(-1, new variant(DISP_E_PARAMNOTFOUND, VT_ERROR), "{947bb102-5d43-11d1-bdbf-00c04fb92675}");
|
||||
// manual counting since rs.RecordCount is -1 (not supported)
|
||||
$i = 0;
|
||||
while (!$rs->EOF) {
|
||||
$rs->MoveNext();
|
||||
$i++;
|
||||
}
|
||||
$rs->Close();
|
||||
$db->Close();
|
||||
var_dump($i);
|
||||
?>
|
||||
--EXPECT--
|
||||
int(1)
|
||||
--CLEAN--
|
||||
<?php
|
||||
unlink(__DIR__ . "/gh8750.mdb");
|
||||
?>
|
||||
36
ext/com_dotnet/tests/gh8750a.phpt
Normal file
36
ext/com_dotnet/tests/gh8750a.phpt
Normal file
@@ -0,0 +1,36 @@
|
||||
--TEST--
|
||||
Bug GH-8750 (Can not create VT_ERROR variant type) - cast and conversion
|
||||
--EXTENSIONS--
|
||||
com_dotnet
|
||||
--FILE--
|
||||
<?php
|
||||
$error = new variant(DISP_E_PARAMNOTFOUND, VT_ERROR);
|
||||
|
||||
// explicit variant_cast() to int is supported if in range
|
||||
echo variant_cast($error, VT_I4), PHP_EOL;
|
||||
|
||||
// however, explicit (int) casts are not supported
|
||||
echo (int) $error, PHP_EOL;
|
||||
|
||||
// nor are implicit conversions
|
||||
try {
|
||||
echo 1 + $error, PHP_EOL;
|
||||
} catch (TypeError $err) {
|
||||
echo $err->getMessage(), PHP_EOL;
|
||||
}
|
||||
|
||||
// we can retrieve the type
|
||||
echo variant_get_type($error), PHP_EOL;
|
||||
|
||||
// and change it via variant_set_type()
|
||||
variant_set_type($error, VT_I4);
|
||||
echo variant_get_type($error), PHP_EOL;
|
||||
?>
|
||||
--EXPECTF--
|
||||
-2147352572
|
||||
|
||||
Warning: Object of class variant could not be converted to int in %s on line %d
|
||||
1
|
||||
Unsupported operand types: int + variant
|
||||
10
|
||||
3
|
||||
Reference in New Issue
Block a user