1
0
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:
Christoph M. Becker
2022-06-21 17:30:42 +02:00
parent 6e24c16c4a
commit 56804e3221
8 changed files with 120 additions and 5 deletions

3
NEWS
View File

@@ -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.

View File

@@ -264,6 +264,7 @@ PHP 8.2 UPGRADE NOTES
========================================
- COM_DOTNET:
. DISP_E_PARAMNOTFOUND
. LOCALE_NEUTRAL
- Curl:

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View 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");
?>

View 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