Commit f7c63f7f479 for php.net
commit f7c63f7f479c2d98740646092354a27753b55457
Author: Gina Peter Banyard <girgias@php.net>
Date: Sat May 30 13:40:35 2026 +0200
ext/openssl: convert PSK callback to FCC
Prevent rechecking the given zval callable every single time
diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c
index f94059673ed..f90d7549ae7 100644
--- a/ext/openssl/xp_ssl.c
+++ b/ext/openssl/xp_ssl.c
@@ -183,8 +183,8 @@ static const unsigned char php_openssl_tls13_aes256gcmsha384_id[] = { 0x13, 0x02
/* Holds PSK callbacks */
typedef struct _php_openssl_psk_callbacks_t {
int refcount;
- zval client_cb;
- zval server_cb;
+ zend_fcall_info_cache client_cb;
+ zend_fcall_info_cache server_cb;
} php_openssl_psk_callbacks_t;
/* Holds session callback */
@@ -1621,7 +1621,7 @@ static SSL_SESSION *php_openssl_psk_build_session(SSL *ssl,
/**
* Invoke a user PHP callback (psk_client_cb or psk_server_cb).
*/
-static zend_result php_openssl_call_psk_cb(php_stream *stream, zval *cb,
+static zend_result php_openssl_call_psk_cb(php_stream *stream, zend_fcall_info_cache *fcc,
const unsigned char *identity, size_t identity_len,
zval *result)
{
@@ -1639,13 +1639,14 @@ static zend_result php_openssl_call_psk_cb(php_stream *stream, zval *cb,
}
ZVAL_UNDEF(&retval);
- call_user_function(NULL, NULL, cb, &retval, argc, args);
+
+ zend_call_known_fcc(fcc, &retval, argc, args, NULL);
if (identity != NULL) {
zval_ptr_dtor(&args[1]);
}
- if (EG(exception)) {
+ if (Z_ISUNDEF(retval)) {
ZVAL_UNDEF(result);
return FAILURE;
}
@@ -1686,7 +1687,7 @@ static unsigned int php_openssl_psk_client_cb(SSL *ssl, const char *hint,
php_openssl_netstream_data_t *sslsock =
(php_openssl_netstream_data_t *)stream->abstract;
if (sslsock == NULL || sslsock->psk_callbacks == NULL
- || Z_ISUNDEF(sslsock->psk_callbacks->client_cb)) {
+ || !ZEND_FCC_INITIALIZED(sslsock->psk_callbacks->client_cb)) {
return 0;
}
@@ -1737,7 +1738,7 @@ static unsigned int php_openssl_psk_server_cb(SSL *ssl, const char *identity,
php_openssl_netstream_data_t *sslsock =
(php_openssl_netstream_data_t *)stream->abstract;
if (sslsock == NULL || sslsock->psk_callbacks == NULL
- || Z_ISUNDEF(sslsock->psk_callbacks->server_cb)) {
+ || !ZEND_FCC_INITIALIZED(sslsock->psk_callbacks->server_cb)) {
return 0;
}
@@ -1793,7 +1794,7 @@ static int php_openssl_psk_use_session_cb(SSL *ssl, const EVP_MD *md,
php_openssl_netstream_data_t *sslsock =
(php_openssl_netstream_data_t *)stream->abstract;
if (sslsock == NULL || sslsock->psk_callbacks == NULL
- || Z_ISUNDEF(sslsock->psk_callbacks->client_cb)) {
+ || !ZEND_FCC_INITIALIZED(sslsock->psk_callbacks->client_cb)) {
return 1;
}
@@ -1860,7 +1861,7 @@ static int php_openssl_psk_find_session_cb(SSL *ssl, const unsigned char *identi
php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t *)stream->abstract;
if (sslsock == NULL || sslsock->psk_callbacks == NULL
- || Z_ISUNDEF(sslsock->psk_callbacks->server_cb)) {
+ || !ZEND_FCC_INITIALIZED(sslsock->psk_callbacks->server_cb)) {
return 1;
}
@@ -1896,9 +1897,10 @@ static int php_openssl_psk_find_session_cb(SSL *ssl, const unsigned char *identi
/* PSK setup */
static zend_result php_openssl_validate_and_allocate_psk_callback(
- php_openssl_netstream_data_t *sslsock, zval *callable,
- const char *callback_name, bool is_persistent)
+ php_openssl_netstream_data_t *sslsock, const zval *callable,
+ bool is_client, bool is_persistent)
{
+ const char *callback_name = is_client ? "psk_client_cb" : "psk_server_cb";
if (is_persistent) {
php_error_docref(NULL, E_WARNING,
"%s is not supported for persistent streams", callback_name);
@@ -1906,7 +1908,8 @@ static zend_result php_openssl_validate_and_allocate_psk_callback(
}
char *is_callable_error = NULL;
- if (!zend_is_callable_ex(callable, NULL, 0, NULL, NULL, &is_callable_error)) {
+ zend_fcall_info_cache fcc = {0};
+ if (!zend_is_callable_ex(callable, NULL, 0, NULL, &fcc, &is_callable_error)) {
if (is_callable_error) {
zend_type_error("%s must be a valid callback, %s",
callback_name, is_callable_error);
@@ -1918,12 +1921,16 @@ static zend_result php_openssl_validate_and_allocate_psk_callback(
}
if (!sslsock->psk_callbacks) {
- sslsock->psk_callbacks = (php_openssl_psk_callbacks_t *)pemalloc(
- sizeof(php_openssl_psk_callbacks_t), is_persistent);
- ZVAL_UNDEF(&sslsock->psk_callbacks->client_cb);
- ZVAL_UNDEF(&sslsock->psk_callbacks->server_cb);
+ sslsock->psk_callbacks = (php_openssl_psk_callbacks_t *)pecalloc(
+ 1, sizeof(php_openssl_psk_callbacks_t), is_persistent);
sslsock->psk_callbacks->refcount = 1;
}
+ zend_fcc_addref(&fcc);
+ if (is_client) {
+ sslsock->psk_callbacks->client_cb = fcc;
+ } else {
+ sslsock->psk_callbacks->server_cb = fcc;
+ }
return SUCCESS;
}
@@ -1938,12 +1945,10 @@ static zend_result php_openssl_setup_client_psk(php_stream *stream,
}
if (FAILURE == php_openssl_validate_and_allocate_psk_callback(
- sslsock, val, "psk_client_cb", php_stream_is_persistent(stream))) {
+ sslsock, val, true, php_stream_is_persistent(stream))) {
return FAILURE;
}
- ZVAL_COPY(&sslsock->psk_callbacks->client_cb, val);
-
#ifndef OPENSSL_NO_PSK
SSL_CTX_set_psk_client_callback(sslsock->ctx, php_openssl_psk_client_cb);
#endif
@@ -1962,12 +1967,10 @@ static zend_result php_openssl_setup_server_psk(php_stream *stream,
}
if (FAILURE == php_openssl_validate_and_allocate_psk_callback(
- sslsock, val, "psk_server_cb", php_stream_is_persistent(stream))) {
+ sslsock, val, false, php_stream_is_persistent(stream))) {
return FAILURE;
}
- ZVAL_COPY(&sslsock->psk_callbacks->server_cb, val);
-
#ifndef OPENSSL_NO_PSK
SSL_CTX_set_psk_server_callback(sslsock->ctx, php_openssl_psk_server_cb);
#endif
@@ -3092,8 +3095,13 @@ static int php_openssl_sockop_close(php_stream *stream, int close_handle) /* {{{
}
if (sslsock->psk_callbacks && --sslsock->psk_callbacks->refcount == 0) {
- zval_ptr_dtor(&sslsock->psk_callbacks->client_cb);
- zval_ptr_dtor(&sslsock->psk_callbacks->server_cb);
+ if (ZEND_FCC_INITIALIZED(sslsock->psk_callbacks->client_cb)) {
+ zend_fcc_dtor(&sslsock->psk_callbacks->client_cb);
+ }
+
+ if (ZEND_FCC_INITIALIZED(sslsock->psk_callbacks->server_cb)) {
+ zend_fcc_dtor(&sslsock->psk_callbacks->server_cb);
+ }
pefree(sslsock->psk_callbacks, php_stream_is_persistent(stream));
}