From fce4c8ffcfee6770b68a541a0e8f3236b2e945ff Mon Sep 17 00:00:00 2001 From: lacatoire Date: Sun, 16 Aug 2026 19:29:18 +0200 Subject: [PATCH] ext/ldap: fix crash in ldap_exop_sync() when $response_data is omitted ldap_exop_sync() always takes the synchronous branch of php_ldap_exop(), which assigns $response_data unconditionally. When the argument is not passed, retdata is NULL and ZEND_TRY_ASSIGN_REF_STRINGL()/ ZEND_TRY_ASSIGN_REF_EMPTY_STRING() dereference it, so any successful ldap_exop_sync($ldap, $oid) call segfaults. Guard the assignment the way the $response_oid one already is. --- ext/ldap/ldap.c | 6 +++-- .../ldap_exop_sync_without_response_data.phpt | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 ext/ldap/tests/ldap_exop_sync_without_response_data.phpt diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 7a089625aa48..734409c352b4 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -4101,10 +4101,12 @@ static void php_ldap_exop(INTERNAL_FUNCTION_PARAMETERS, bool force_sync) { } if (lretdata) { - ZEND_TRY_ASSIGN_REF_STRINGL(retdata, lretdata->bv_val, lretdata->bv_len); + if (retdata) { + ZEND_TRY_ASSIGN_REF_STRINGL(retdata, lretdata->bv_val, lretdata->bv_len); + } ldap_memfree(lretdata->bv_val); ldap_memfree(lretdata); - } else { + } else if (retdata) { ZEND_TRY_ASSIGN_REF_EMPTY_STRING(retdata); } diff --git a/ext/ldap/tests/ldap_exop_sync_without_response_data.phpt b/ext/ldap/tests/ldap_exop_sync_without_response_data.phpt new file mode 100644 index 000000000000..111900c6a05a --- /dev/null +++ b/ext/ldap/tests/ldap_exop_sync_without_response_data.phpt @@ -0,0 +1,22 @@ +--TEST-- +ldap_exop_sync() - without the response_data argument +--EXTENSIONS-- +ldap +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +bool(true) +bool(true) +string(%d) "dn:%s"