diff --git a/NEWS b/NEWS index 2b7a26cb8bb7..a79edf8c27ae 100644 --- a/NEWS +++ b/NEWS @@ -37,6 +37,10 @@ PHP NEWS . Fixed bug GH-24697 (PHP_HTTP_PARSER_STRICT build option doesn't work). (ndossche, devnexen) +- COM: + . Fixed bug GH-25008 (com_event_sink() and com_print_typeinfo() crash + resolving an event source with no loaded typelib). (Ilia Alshanetsky) + - Curl: . Fix use-after-free of CURLOPT_STDERR stream on cloned curl handle. (lacatoire) diff --git a/ext/com_dotnet/com_typeinfo.c b/ext/com_dotnet/com_typeinfo.c index 28306b5609b0..31885105ac0f 100644 --- a/ext/com_dotnet/com_typeinfo.c +++ b/ext/com_dotnet/com_typeinfo.c @@ -326,6 +326,27 @@ ITypeInfo *php_com_locate_typeinfo(zend_string *type_lib_name, php_com_dotnet_ob php_error_docref(NULL, E_WARNING, "IProvideClassInfo: this code not yet written!"); IProvideClassInfo_Release(pci); } + if (gotguid) { + ITypeInfo *srcinfo = obj->typeinfo; + bool release_srcinfo = false; + unsigned int idx; + ITypeLib *container = NULL; + + if (!srcinfo) { + ITypeInfo *fetched = NULL; + + if (SUCCEEDED(IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &fetched)) && fetched) { + srcinfo = fetched; + release_srcinfo = true; + } + } + if (srcinfo && SUCCEEDED(ITypeInfo_GetContainingTypeLib(srcinfo, &container, &idx))) { + typelib = container; + } + if (release_srcinfo) { + ITypeInfo_Release(srcinfo); + } + } } } else if (dispatch_name == NULL) { if (obj->typeinfo) { @@ -408,8 +429,12 @@ ITypeInfo *php_com_locate_typeinfo(zend_string *type_lib_name, php_com_dotnet_ob efree(olename); - } else if (gotguid) { - ITypeLib_GetTypeInfoOfGuid(typelib, &iid, &typeinfo); + } else if (gotguid && typelib) { + ITypeInfo *found = NULL; + + if (SUCCEEDED(ITypeLib_GetTypeInfoOfGuid(typelib, &iid, &found))) { + typeinfo = found; + } } if (typelib) { @@ -639,6 +664,8 @@ bool php_com_process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, bool p } } else { zend_throw_error(NULL, "Type kind must be dispatchable, %08x given", attr->typekind); + ITypeInfo_ReleaseTypeAttr(typeinfo, attr); + return false; } ITypeInfo_ReleaseTypeAttr(typeinfo, attr); diff --git a/ext/com_dotnet/tests/gh25008.phpt b/ext/com_dotnet/tests/gh25008.phpt new file mode 100755 index 000000000000..19e461d34519 --- /dev/null +++ b/ext/com_dotnet/tests/gh25008.phpt @@ -0,0 +1,59 @@ +--TEST-- +GH-25008 (com_event_sink and com_print_typeinfo crash on a NULL source typelib) +--EXTENSIONS-- +com_dotnet +--INI-- +com.autoregister_typelib=0 +--SKIPIF-- + +--FILE-- +getMessage(), "\n"; +} + +ob_start(); +$events = com_print_typeinfo($o, null, true); +$events_dump = ob_get_clean(); +echo 'events: '; +var_dump($events); +echo (str_contains($events_dump, 'class IWinHttpRequestEvents') + && str_contains($events_dump, '{F97F4E15-B787-4212-80D1-D380CBBF982E}') + && str_contains($events_dump, 'function OnResponseStart')) + ? "events interface\n" : "events missing\n"; + +ob_start(); +$request = com_print_typeinfo($o, null, false); +$request_dump = ob_get_clean(); +echo 'request: '; +var_dump($request); +echo (str_contains($request_dump, 'class IWinHttpRequest') + && str_contains($request_dump, '{016FE2EC-B2C8-45F8-B23B-39E53A75396B}')) + ? "request interface\n" : "request missing\n"; + +$d = new COM('Scripting.Dictionary'); +echo 'dictionary: '; +var_dump(com_event_sink($d, new stdClass)); +?> +--EXPECTF-- +sink: Error: Type kind must be dispatchable, 00000003 given +events: bool(true) +events interface +request: bool(true) +request interface +dictionary: +Warning: com_event_sink(): IProvideClassInfo: this code not yet written! in %s on line %d +bool(false)