diff --git a/ext/com_dotnet/com_extension.c b/ext/com_dotnet/com_extension.c index 5782102201f61..95361a4b9a9ed 100644 --- a/ext/com_dotnet/com_extension.c +++ b/ext/com_dotnet/com_extension.c @@ -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 diff --git a/ext/com_dotnet/com_extension.stub.php b/ext/com_dotnet/com_extension.stub.php index 54f31992ef7a4..20b255949f868 100644 --- a/ext/com_dotnet/com_extension.stub.php +++ b/ext/com_dotnet/com_extension.stub.php @@ -264,6 +264,11 @@ * @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 diff --git a/ext/com_dotnet/com_extension_arginfo.h b/ext/com_dotnet/com_extension_arginfo.h index fcca1ecbeefc1..d2829031b360b 100644 --- a/ext/com_dotnet/com_extension_arginfo.h +++ b/ext/com_dotnet/com_extension_arginfo.h @@ -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); diff --git a/ext/com_dotnet/com_variant.c b/ext/com_dotnet/com_variant.c index 40106e3d8f4ff..b40ac6a5c31f9 100644 --- a/ext/com_dotnet/com_variant.c +++ b/ext/com_dotnet/com_variant.c @@ -92,7 +92,7 @@ static void safe_array_from_zval(VARIANT *v, zval *z, int codepage) } } -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); diff --git a/ext/com_dotnet/tests/gh8750.phpt b/ext/com_dotnet/tests/gh8750.phpt new file mode 100644 index 0000000000000..7187c56bfd681 --- /dev/null +++ b/ext/com_dotnet/tests/gh8750.phpt @@ -0,0 +1,47 @@ +--TEST-- +Bug GH-8750 (Can not create VT_ERROR variant type) +--EXTENSIONS-- +com_dotnet +--SKIPIF-- +Create("Provider=$provider;Data Source=$filename"); +} catch (com_exception) { + die("skip $provider provider not available"); +} +$catalog = null; +@unlink($filename); +?> +--FILE-- +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-- + diff --git a/ext/com_dotnet/tests/gh8750a.phpt b/ext/com_dotnet/tests/gh8750a.phpt new file mode 100644 index 0000000000000..0e1762f8b71ad --- /dev/null +++ b/ext/com_dotnet/tests/gh8750a.phpt @@ -0,0 +1,36 @@ +--TEST-- +Bug GH-8750 (Can not create VT_ERROR variant type) - cast and conversion +--EXTENSIONS-- +com_dotnet +--FILE-- +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