Skip to content

Commit 425cd3d

Browse files
committed
ext/openssl: convert SESSION callback to FCC
Prevent rechecking the given zval callable every single time
1 parent f7c63f7 commit 425cd3d

1 file changed

Lines changed: 71 additions & 50 deletions

File tree

ext/openssl/xp_ssl.c

Lines changed: 71 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,9 @@ typedef struct _php_openssl_psk_callbacks_t {
190190
/* Holds session callback */
191191
typedef struct _php_openssl_session_callbacks_t {
192192
int refcount;
193-
zval new_cb;
194-
zval get_cb;
195-
zval remove_cb;
193+
zend_fcall_info_cache new_cb;
194+
zend_fcall_info_cache get_cb;
195+
zend_fcall_info_cache remove_cb;
196196
} php_openssl_session_callbacks_t;
197197

198198
/* This implementation is very closely tied to the that of the native
@@ -2004,15 +2004,11 @@ static int php_openssl_session_new_cb(SSL *ssl, SSL_SESSION *session)
20042004
SSL_SESSION_up_ref(session);
20052005

20062006
zval args[2];
2007-
zval retval;
20082007

20092008
ZVAL_RES(&args[0], stream->res);
20102009
php_openssl_session_object_init(&args[1], session);
20112010

2012-
if (call_user_function(EG(function_table), NULL, &sslsock->session_callbacks->new_cb,
2013-
&retval, 2, args) == SUCCESS) {
2014-
zval_ptr_dtor(&retval);
2015-
}
2011+
zend_call_known_fcc(&sslsock->session_callbacks->new_cb, NULL, 2, args, NULL);
20162012

20172013
zval_ptr_dtor(&args[1]);
20182014

@@ -2045,22 +2041,21 @@ static SSL_SESSION *php_openssl_session_get_cb(SSL *ssl, const unsigned char *se
20452041

20462042
SSL_SESSION *session = NULL;
20472043

2048-
if (call_user_function(EG(function_table), NULL, &sslsock->session_callbacks->get_cb,
2049-
&retval, 2, args) == SUCCESS) {
2050-
if (php_openssl_is_session_ce(&retval)) {
2051-
/* Get session from object and increment ref since OpenSSL will own it */
2052-
php_openssl_session_object *obj = Z_OPENSSL_SESSION_P(&retval);
2053-
if (obj->session) {
2054-
SSL_SESSION_up_ref(obj->session);
2055-
session = obj->session;
2056-
}
2057-
} else if (Z_TYPE(retval) != IS_NULL) {
2058-
zend_type_error("session_get_cb return type must be null or OpenSSLSession");
2044+
zend_call_known_fcc(&sslsock->session_callbacks->get_cb, &retval, 2, args, NULL);
2045+
zval_ptr_dtor(&args[1]);
2046+
2047+
if (php_openssl_is_session_ce(&retval)) {
2048+
/* Get session from object and increment ref since OpenSSL will own it */
2049+
php_openssl_session_object *obj = Z_OPENSSL_SESSION_P(&retval);
2050+
if (obj->session) {
2051+
SSL_SESSION_up_ref(obj->session);
2052+
session = obj->session;
20592053
}
2054+
} else if (Z_TYPE(retval) != IS_NULL) {
2055+
zend_type_error("session_get_cb return type must be null or OpenSSLSession");
20602056
}
20612057

20622058
zval_ptr_dtor(&retval);
2063-
zval_ptr_dtor(&args[1]);
20642059

20652060
*copy = 0;
20662061
return session;
@@ -2085,28 +2080,41 @@ static void php_openssl_session_remove_cb(SSL_CTX *ctx, SSL_SESSION *session)
20852080
const unsigned char *session_id = SSL_SESSION_get_id(session, &session_id_len);
20862081

20872082
zval args[2];
2088-
zval retval;
20892083

20902084
ZVAL_RES(&args[0], stream->res);
20912085
ZVAL_STRINGL(&args[1], (char *)session_id, session_id_len);
20922086

2093-
if (call_user_function(EG(function_table), NULL, &sslsock->session_callbacks->remove_cb,
2094-
&retval, 2, args) == SUCCESS) {
2095-
zval_ptr_dtor(&retval);
2096-
}
2097-
2087+
zend_call_known_fcc(&sslsock->session_callbacks->remove_cb, NULL, 2, args, NULL);
20982088
zval_ptr_dtor(&args[1]);
20992089
}
21002090

2091+
2092+
enum php_openssl_session_callback_type {
2093+
PHP_OPENSSL_NEW_CB,
2094+
PHP_OPENSSL_GET_CB,
2095+
PHP_OPENSSL_REMOVE_CB,
2096+
};
21012097
/**
21022098
* Validate callable and allocate callback structure if needed.
21032099
*/
2104-
static zend_result php_openssl_validate_and_allocate_callback(
2105-
php_openssl_netstream_data_t *sslsock, zval *callable,
2106-
const char *callback_name, bool is_persistent)
2100+
static zend_result php_openssl_validate_and_allocate_session_callback(
2101+
php_openssl_netstream_data_t *sslsock, const zval *callable,
2102+
enum php_openssl_session_callback_type cb_type, bool is_persistent)
21072103
{
2108-
zend_fcall_info_cache fcc;
21092104
char *is_callable_error = NULL;
2105+
const char *callback_name;
2106+
2107+
switch (cb_type) {
2108+
case PHP_OPENSSL_NEW_CB:
2109+
callback_name = "session_new_cb";
2110+
break;
2111+
case PHP_OPENSSL_GET_CB:
2112+
callback_name = "session_get_cb";
2113+
break;
2114+
case PHP_OPENSSL_REMOVE_CB:
2115+
callback_name = "session_remove_cb";
2116+
break;
2117+
}
21102118

21112119
/* Callbacks not supported for persistent streams */
21122120
if (is_persistent) {
@@ -2116,6 +2124,7 @@ static zend_result php_openssl_validate_and_allocate_callback(
21162124
}
21172125

21182126
/* Validate callable */
2127+
zend_fcall_info_cache fcc;
21192128
if (!zend_is_callable_ex(callable, NULL, 0, NULL, &fcc, &is_callable_error)) {
21202129
if (is_callable_error) {
21212130
zend_type_error("%s must be a valid callback, %s", callback_name, is_callable_error);
@@ -2128,14 +2137,24 @@ static zend_result php_openssl_validate_and_allocate_callback(
21282137

21292138
/* Allocate callback structure if not already allocated */
21302139
if (!sslsock->session_callbacks) {
2131-
sslsock->session_callbacks = (php_openssl_session_callbacks_t *)pemalloc(
2132-
sizeof(php_openssl_session_callbacks_t), is_persistent);
2133-
ZVAL_UNDEF(&sslsock->session_callbacks->new_cb);
2134-
ZVAL_UNDEF(&sslsock->session_callbacks->get_cb);
2135-
ZVAL_UNDEF(&sslsock->session_callbacks->remove_cb);
2140+
sslsock->session_callbacks = (php_openssl_session_callbacks_t *)pecalloc(
2141+
1, sizeof(php_openssl_session_callbacks_t), is_persistent);
21362142
sslsock->session_callbacks->refcount = 1;
21372143
}
21382144

2145+
zend_fcc_addref(&fcc);
2146+
switch (cb_type) {
2147+
case PHP_OPENSSL_NEW_CB:
2148+
sslsock->session_callbacks->new_cb = fcc;
2149+
break;
2150+
case PHP_OPENSSL_GET_CB:
2151+
sslsock->session_callbacks->get_cb = fcc;
2152+
break;
2153+
case PHP_OPENSSL_REMOVE_CB:
2154+
sslsock->session_callbacks->remove_cb = fcc;
2155+
break;
2156+
}
2157+
21392158
return SUCCESS;
21402159
}
21412160

@@ -2159,12 +2178,11 @@ static zend_result php_openssl_setup_client_session(php_stream *stream,
21592178
}
21602179

21612180
if (GET_VER_OPT("session_new_cb")) {
2162-
if (FAILURE == php_openssl_validate_and_allocate_callback(
2163-
sslsock, val, "session_new_cb", is_persistent)) {
2181+
if (FAILURE == php_openssl_validate_and_allocate_session_callback(
2182+
sslsock, val, PHP_OPENSSL_NEW_CB, is_persistent)) {
21642183
return FAILURE;
21652184
}
21662185

2167-
ZVAL_COPY(&sslsock->session_callbacks->new_cb, val);
21682186
SSL_CTX_sess_set_new_cb(sslsock->ctx, php_openssl_session_new_cb);
21692187
enable_client_cache = true;
21702188
}
@@ -2207,11 +2225,10 @@ static zend_result php_openssl_setup_server_session(php_stream *stream,
22072225

22082226
/* Check for session_get_cb first (determines cache mode) */
22092227
if (GET_VER_OPT("session_get_cb")) {
2210-
if (FAILURE == php_openssl_validate_and_allocate_callback(
2211-
sslsock, val, "session_new_cb", is_persistent)) {
2228+
if (FAILURE == php_openssl_validate_and_allocate_session_callback(
2229+
sslsock, val, PHP_OPENSSL_GET_CB, is_persistent)) {
22122230
return FAILURE;
22132231
}
2214-
ZVAL_COPY(&sslsock->session_callbacks->get_cb, val);
22152232
has_get_cb = true;
22162233
}
22172234

@@ -2227,11 +2244,10 @@ static zend_result php_openssl_setup_server_session(php_stream *stream,
22272244

22282245
/* Check for session_new_cb */
22292246
if (GET_VER_OPT("session_new_cb")) {
2230-
if (FAILURE == php_openssl_validate_and_allocate_callback(
2231-
sslsock, val, "session_new_cb", is_persistent)) {
2247+
if (FAILURE == php_openssl_validate_and_allocate_session_callback(
2248+
sslsock, val, PHP_OPENSSL_NEW_CB, is_persistent)) {
22322249
return FAILURE;
22332250
}
2234-
ZVAL_COPY(&sslsock->session_callbacks->new_cb, val);
22352251
has_new_cb = true;
22362252

22372253
if (!has_session_id_context &&
@@ -2249,12 +2265,11 @@ static zend_result php_openssl_setup_server_session(php_stream *stream,
22492265

22502266
/* Check for session_remove_cb (optional) */
22512267
if (GET_VER_OPT("session_remove_cb")) {
2252-
if (FAILURE == php_openssl_validate_and_allocate_callback(
2253-
sslsock, val, "session_remove_cb", is_persistent)) {
2268+
if (FAILURE == php_openssl_validate_and_allocate_session_callback(
2269+
sslsock, val, PHP_OPENSSL_REMOVE_CB, is_persistent)) {
22542270
return FAILURE;
22552271
}
22562272

2257-
ZVAL_COPY(&sslsock->session_callbacks->remove_cb, val);
22582273
has_remove_cb = true;
22592274
}
22602275

@@ -3088,9 +3103,15 @@ static int php_openssl_sockop_close(php_stream *stream, int close_handle) /* {{{
30883103
}
30893104

30903105
if (sslsock->session_callbacks && --sslsock->session_callbacks->refcount == 0) {
3091-
zval_ptr_dtor(&sslsock->session_callbacks->new_cb);
3092-
zval_ptr_dtor(&sslsock->session_callbacks->get_cb);
3093-
zval_ptr_dtor(&sslsock->session_callbacks->remove_cb);
3106+
if (ZEND_FCC_INITIALIZED(sslsock->session_callbacks->new_cb)) {
3107+
zend_fcc_dtor(&sslsock->session_callbacks->new_cb);
3108+
}
3109+
if (ZEND_FCC_INITIALIZED(sslsock->session_callbacks->get_cb)) {
3110+
zend_fcc_dtor(&sslsock->session_callbacks->get_cb);
3111+
}
3112+
if (ZEND_FCC_INITIALIZED(sslsock->session_callbacks->remove_cb)) {
3113+
zend_fcc_dtor(&sslsock->session_callbacks->remove_cb);
3114+
}
30943115
pefree(sslsock->session_callbacks, php_stream_is_persistent(stream));
30953116
}
30963117

0 commit comments

Comments
 (0)