@@ -190,9 +190,9 @@ typedef struct _php_openssl_psk_callbacks_t {
190190/* Holds session callback */
191191typedef 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