Fix format specifiers and arguments in com_dotnet (GH-15398)

This is mostly about minor glitches (signedness or length confusion),
but also fixes two occasions where `zend_string`s still have been
regarded as `char *`.

We also add a regression test case for failing property name lookup,
since that is the most relevant issue we're fixing here.
This commit is contained in:
Christoph M. Becker 2024-08-15 10:59:10 +02:00 committed by GitHub
parent 04320d2fba
commit 4b2dc58651
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 31 additions and 16 deletions

View file

@ -392,7 +392,7 @@ HRESULT php_com_invoke_helper(php_com_dotnet_object *obj, DISPID id_member,
default: default:
desc = php_win32_error_to_msg(hr); desc = php_win32_error_to_msg(hr);
spprintf(&msg, 0, "Error [0x%08x] %s", hr, desc); spprintf(&msg, 0, "Error [0x%08lx] %s", hr, desc);
php_win32_error_msg_free(desc); php_win32_error_msg_free(desc);
break; break;
} }
@ -639,7 +639,7 @@ zend_result php_com_do_invoke(php_com_dotnet_object *obj, zend_string *name,
if (FAILED(hr)) { if (FAILED(hr)) {
char *winerr = php_win32_error_to_msg(hr); char *winerr = php_win32_error_to_msg(hr);
spprintf(&msg, 0, "Unable to lookup `%s': %s", name, winerr); spprintf(&msg, 0, "Unable to lookup `%s': %s", ZSTR_VAL(name), winerr);
php_win32_error_msg_free(winerr); php_win32_error_msg_free(winerr);
php_com_throw_exception(hr, msg); php_com_throw_exception(hr, msg);
efree(msg); efree(msg);

View file

@ -245,7 +245,7 @@ PHP_METHOD(dotnet, __construct)
if (FAILED(hr)) { if (FAILED(hr)) {
char buf[1024]; char buf[1024];
char *err = php_win32_error_to_msg(hr); char *err = php_win32_error_to_msg(hr);
snprintf(buf, sizeof(buf), "Failed to init .Net runtime [%s] [0x%08x] %s", where, hr, err); snprintf(buf, sizeof(buf), "Failed to init .Net runtime [%s] [0x%08lx] %s", where, hr, err);
php_win32_error_msg_free(err); php_win32_error_msg_free(err);
php_com_throw_exception(hr, buf); php_com_throw_exception(hr, buf);
RETURN_THROWS(); RETURN_THROWS();
@ -258,7 +258,7 @@ PHP_METHOD(dotnet, __construct)
if (FAILED(hr)) { if (FAILED(hr)) {
char buf[1024]; char buf[1024];
char *err = php_win32_error_to_msg(hr); char *err = php_win32_error_to_msg(hr);
snprintf(buf, sizeof(buf), "Failed to re-init .Net domain [%s] [0x%08x] %s", where, hr, err); snprintf(buf, sizeof(buf), "Failed to re-init .Net domain [%s] [0x%08lx] %s", where, hr, err);
php_win32_error_msg_free(err); php_win32_error_msg_free(err);
php_com_throw_exception(hr, buf); php_com_throw_exception(hr, buf);
ZVAL_NULL(object); ZVAL_NULL(object);
@ -270,7 +270,7 @@ PHP_METHOD(dotnet, __construct)
if (FAILED(hr)) { if (FAILED(hr)) {
char buf[1024]; char buf[1024];
char *err = php_win32_error_to_msg(hr); char *err = php_win32_error_to_msg(hr);
snprintf(buf, sizeof(buf), "Failed to re-init .Net domain [%s] [0x%08x] %s", where, hr, err); snprintf(buf, sizeof(buf), "Failed to re-init .Net domain [%s] [0x%08lx] %s", where, hr, err);
php_win32_error_msg_free(err); php_win32_error_msg_free(err);
php_com_throw_exception(hr, buf); php_com_throw_exception(hr, buf);
ZVAL_NULL(object); ZVAL_NULL(object);
@ -344,7 +344,7 @@ PHP_METHOD(dotnet, __construct)
if (ret == FAILURE) { if (ret == FAILURE) {
char buf[1024]; char buf[1024];
char *err = php_win32_error_to_msg(hr); char *err = php_win32_error_to_msg(hr);
snprintf(buf, sizeof(buf), "Failed to instantiate .Net object [%s] [0x%08x] %s", where, hr, err); snprintf(buf, sizeof(buf), "Failed to instantiate .Net object [%s] [0x%08lx] %s", where, hr, err);
php_win32_error_msg_free(err); php_win32_error_msg_free(err);
php_com_throw_exception(hr, buf); php_com_throw_exception(hr, buf);
RETURN_THROWS(); RETURN_THROWS();

View file

@ -543,7 +543,7 @@ bool php_com_process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, bool p
/* first element is the function name */ /* first element is the function name */
SysFreeString(names[0]); SysFreeString(names[0]);
php_printf("\t/* DISPID=%d */\n", func->memid); php_printf("\t/* DISPID=%ld */\n", func->memid);
if (func->elemdescFunc.tdesc.vt != VT_VOID) { if (func->elemdescFunc.tdesc.vt != VT_VOID) {
php_printf("\t/* %s [%d] */\n", php_printf("\t/* %s [%d] */\n",

View file

@ -53,7 +53,7 @@ static inline void trace(char *fmt, ...)
va_list ap; va_list ap;
char buf[4096]; char buf[4096];
snprintf(buf, sizeof(buf), "T=%08x ", GetCurrentThreadId()); snprintf(buf, sizeof(buf), "T=%08lx ", GetCurrentThreadId());
OutputDebugString(buf); OutputDebugString(buf);
va_start(ap, fmt); va_start(ap, fmt);
@ -70,7 +70,7 @@ static inline void trace(char *fmt, ...)
if (COMG(rshutdown_started)) { \ if (COMG(rshutdown_started)) { \
trace(" PHP Object:%p (name:unknown) %s\n", Z_OBJ(disp->object), methname); \ trace(" PHP Object:%p (name:unknown) %s\n", Z_OBJ(disp->object), methname); \
} else { \ } else { \
trace(" PHP Object:%p (name:%s) %s\n", Z_OBJ(disp->object), Z_OBJCE(disp->object)->name->val, methname); \ trace(" PHP Object:%p (name:%s) %s\n", Z_OBJ(disp->object), ZSTR_VAL(Z_OBJCE(disp->object)->name), methname); \
} \ } \
if (GetCurrentThreadId() != disp->engine_thread) { \ if (GetCurrentThreadId() != disp->engine_thread) { \
return RPC_E_WRONG_THREAD; \ return RPC_E_WRONG_THREAD; \
@ -109,7 +109,7 @@ static ULONG STDMETHODCALLTYPE disp_release(IDispatchEx *This)
FETCH_DISP("Release"); FETCH_DISP("Release");
ret = InterlockedDecrement(&disp->refcount); ret = InterlockedDecrement(&disp->refcount);
trace("-- refcount now %d\n", ret); trace("-- refcount now %lu\n", ret);
if (ret == 0) { if (ret == 0) {
/* destroy it */ /* destroy it */
disp_destructor(disp); disp_destructor(disp);
@ -201,7 +201,7 @@ static HRESULT STDMETHODCALLTYPE disp_getdispid(
name = php_com_olestring_to_string(bstrName, COMG(code_page)); name = php_com_olestring_to_string(bstrName, COMG(code_page));
trace("Looking for %s, namelen=%d in %p\n", ZSTR_VAL(name), ZSTR_LEN(name), disp->name_to_dispid); trace("Looking for %s, namelen=%lu in %p\n", ZSTR_VAL(name), ZSTR_LEN(name), disp->name_to_dispid);
/* Lookup the name in the hash */ /* Lookup the name in the hash */
if ((tmp = zend_hash_find(disp->name_to_dispid, name)) != NULL) { if ((tmp = zend_hash_find(disp->name_to_dispid, name)) != NULL) {
@ -235,7 +235,7 @@ static HRESULT STDMETHODCALLTYPE disp_invokeex(
if (NULL != (name = zend_hash_index_find(disp->dispid_to_name, id))) { if (NULL != (name = zend_hash_index_find(disp->dispid_to_name, id))) {
/* TODO: add support for overloaded objects */ /* TODO: add support for overloaded objects */
trace("-- Invoke: %d %20s [%d] flags=%08x args=%d\n", id, Z_STRVAL_P(name), Z_STRLEN_P(name), wFlags, pdp->cArgs); trace("-- Invoke: %ld %20s [%lu] flags=%08x args=%u\n", id, Z_STRVAL_P(name), Z_STRLEN_P(name), wFlags, pdp->cArgs);
/* convert args into zvals. /* convert args into zvals.
* Args are in reverse order */ * Args are in reverse order */
@ -246,7 +246,7 @@ static HRESULT STDMETHODCALLTYPE disp_invokeex(
arg = &pdp->rgvarg[ pdp->cArgs - 1 - i]; arg = &pdp->rgvarg[ pdp->cArgs - 1 - i];
trace("alloc zval for arg %d VT=%08x\n", i, V_VT(arg)); trace("alloc zval for arg %u VT=%08x\n", i, V_VT(arg));
php_com_wrap_variant(&params[i], arg, COMG(code_page)); php_com_wrap_variant(&params[i], arg, COMG(code_page));
} }
@ -275,7 +275,7 @@ static HRESULT STDMETHODCALLTYPE disp_invokeex(
VARIANT *srcvar = &obj->v; VARIANT *srcvar = &obj->v;
VARIANT *dstvar = &pdp->rgvarg[ pdp->cArgs - 1 - i]; VARIANT *dstvar = &pdp->rgvarg[ pdp->cArgs - 1 - i];
if ((V_VT(dstvar) & VT_BYREF) && obj->modified ) { if ((V_VT(dstvar) & VT_BYREF) && obj->modified ) {
trace("percolate modified value for arg %d VT=%08x\n", i, V_VT(dstvar)); trace("percolate modified value for arg %u VT=%08x\n", i, V_VT(dstvar));
php_com_copy_variant(dstvar, srcvar); php_com_copy_variant(dstvar, srcvar);
} }
} }
@ -311,7 +311,7 @@ static HRESULT STDMETHODCALLTYPE disp_invokeex(
} }
} else { } else {
trace("InvokeEx: I don't support DISPID=%d\n", id); trace("InvokeEx: I don't support DISPID=%ld\n", id);
} }
return ret; return ret;
@ -508,7 +508,7 @@ static php_dispatchex *disp_constructor(zval *object)
{ {
php_dispatchex *disp = (php_dispatchex*)CoTaskMemAlloc(sizeof(php_dispatchex)); php_dispatchex *disp = (php_dispatchex*)CoTaskMemAlloc(sizeof(php_dispatchex));
trace("constructing a COM wrapper for PHP object %p (%s)\n", object, Z_OBJCE_P(object)->name); trace("constructing a COM wrapper for PHP object %p (%s)\n", object, ZSTR_VAL(Z_OBJCE_P(object)->name));
if (disp == NULL) if (disp == NULL)
return NULL; return NULL;

View file

@ -0,0 +1,15 @@
--TEST--
Property name lookup error
--EXTENSIONS--
com_dotnet
--FILE--
<?php
$dict = new COM("Scripting.Dictionary");
try {
$dict->unknownProperty;
} catch (com_exception $ex) {
echo $ex->getMessage(), "\n";
}
?>
--EXPECTF--
Unable to lookup `unknownProperty': %s