@@ -102,6 +102,7 @@ zend_class_entry *php_session_update_timestamp_iface_entry;
102102
103103static zend_result php_session_send_cookie (void );
104104static zend_result php_session_abort (void );
105+ static void proposed_session_id_to_session_id (zval * proposed_session_id );
105106
106107/* Initialized in MINIT, readonly otherwise. */
107108static int my_module_number = 0 ;
@@ -369,7 +370,7 @@ PHPAPI zend_string *php_session_create_id(PS_CREATE_SID_ARGS)
369370 * ps_modules appropriately */
370371PHPAPI zend_result php_session_valid_key (const char * key )
371372{
372- size_t len ;
373+ size_t key_len ;
373374 const char * p ;
374375 char c ;
375376
@@ -384,11 +385,11 @@ PHPAPI zend_result php_session_valid_key(const char *key)
384385 }
385386 }
386387
387- len = p - key ;
388+ key_len = p - key ;
388389
389390 /* Somewhat arbitrary length limit here, but should be way more than
390391 anyone needs and avoids file-level warnings later on if we exceed MAX_PATH */
391- if (len == 0 || len > PS_MAX_SID_LENGTH ) {
392+ if (key_len == 0 || key_len > PS_MAX_SID_LENGTH ) {
392393 return FAILURE ;
393394 }
394395
@@ -398,20 +399,21 @@ PHPAPI zend_result php_session_valid_key(const char *key)
398399
399400static zend_long php_session_gc (bool immediate )
400401{
401- zend_long num = -1 ;
402+ zend_long sessions_deleted = -1 ;
402403 bool collect = immediate ;
403404
404405 /* GC must be done before reading session data. */
405406 if ((PS (mod_data ) || PS (mod_user_implemented ))) {
407+ /* Use probability-based GC if not forced and probability is configured */
406408 if (!collect && PS (gc_probability ) > 0 ) {
407409 collect = php_random_range (PS (random ), 0 , PS (gc_divisor ) - 1 ) < PS (gc_probability );
408410 }
409411
410412 if (collect ) {
411- PS (mod )-> s_gc (& PS (mod_data ), PS (gc_maxlifetime ), & num );
413+ PS (mod )-> s_gc (& PS (mod_data ), PS (gc_maxlifetime ), & sessions_deleted );
412414 }
413415 }
414- return num ;
416+ return sessions_deleted ;
415417}
416418
417419static zend_result php_session_initialize (void )
@@ -1441,37 +1443,132 @@ static zend_result php_session_send_cookie(void)
14411443
14421444PHPAPI const ps_module * _php_find_ps_module (const char * name )
14431445{
1444- const ps_module * ret = NULL ;
1445- const ps_module * * mod ;
1446- int i ;
1446+ const ps_module * found_module = NULL ;
1447+ const ps_module * * current_module ;
1448+ int module_index ;
14471449
1448- for (i = 0 , mod = ps_modules ; i < MAX_MODULES ; i ++ , mod ++ ) {
1449- if (* mod && !strcasecmp (name , (* mod )-> s_name )) {
1450- ret = * mod ;
1450+ for (module_index = 0 , current_module = ps_modules ; module_index < MAX_MODULES ; module_index ++ , current_module ++ ) {
1451+ if (* current_module && !strcasecmp (name , (* current_module )-> s_name )) {
1452+ found_module = * current_module ;
14511453 break ;
14521454 }
14531455 }
1454- return ret ;
1456+ return found_module ;
14551457}
14561458
14571459PHPAPI const ps_serializer * _php_find_ps_serializer (const char * name )
14581460{
1459- const ps_serializer * ret = NULL ;
1460- const ps_serializer * mod ;
1461+ const ps_serializer * found_serializer = NULL ;
1462+ const ps_serializer * current_serializer ;
14611463
1462- for (mod = ps_serializers ; mod -> name ; mod ++ ) {
1463- if (!strcasecmp (name , mod -> name )) {
1464- ret = mod ;
1464+ for (current_serializer = ps_serializers ; current_serializer -> name ; current_serializer ++ ) {
1465+ if (!strcasecmp (name , current_serializer -> name )) {
1466+ found_serializer = current_serializer ;
14651467 break ;
14661468 }
14671469 }
1468- return ret ;
1470+ return found_serializer ;
1471+ }
1472+
1473+ static bool should_invalidate_session_for_external_referer (void )
1474+ {
1475+ zval * referer_data ;
1476+
1477+ /* No external referer check configured */
1478+ if (!PS (id ) || PS (extern_referer_chk )[0 ] == '\0' ) {
1479+ return false;
1480+ }
1481+
1482+ /* No SERVER globals available */
1483+ if (Z_ISUNDEF (PG (http_globals )[TRACK_VARS_SERVER ])) {
1484+ return false;
1485+ }
1486+
1487+ /* Get HTTP_REFERER header */
1488+ referer_data = zend_hash_str_find (Z_ARRVAL (PG (http_globals )[TRACK_VARS_SERVER ]), ZEND_STRL ("HTTP_REFERER" ));
1489+ if (!referer_data || Z_TYPE_P (referer_data ) != IS_STRING || Z_STRLEN_P (referer_data ) == 0 ) {
1490+ return false;
1491+ }
1492+
1493+ /* Check if referer contains expected string */
1494+ return strstr (Z_STRVAL_P (referer_data ), PS (extern_referer_chk )) == NULL ;
1495+ }
1496+
1497+ static void try_find_session_id_in_global (const char * global_name , size_t global_name_len )
1498+ {
1499+ zval * global_data , * potential_session_id ;
1500+
1501+ if (PS (id )) {
1502+ return ;
1503+ }
1504+
1505+ global_data = zend_hash_str_find (& EG (symbol_table ), global_name , global_name_len );
1506+ if (!global_data ) {
1507+ return ;
1508+ }
1509+
1510+ ZVAL_DEREF (global_data );
1511+ if (Z_TYPE_P (global_data ) != IS_ARRAY ) {
1512+ return ;
1513+ }
1514+
1515+ potential_session_id = zend_hash_find (Z_ARRVAL_P (global_data ), PS (session_name ));
1516+ if (potential_session_id ) {
1517+ proposed_session_id_to_session_id (potential_session_id );
1518+ }
1519+ }
1520+
1521+ static bool php_can_change_session_setting (const char * setting_name , bool check_cookies )
1522+ {
1523+ if (PS (session_status ) == php_session_active ) {
1524+ char error_msg [256 ];
1525+ snprintf (error_msg , sizeof (error_msg ), "Session %s cannot be changed when a session is active" , setting_name );
1526+ php_session_session_already_started_error (E_WARNING , error_msg );
1527+
1528+ return false;
1529+ }
1530+
1531+ if (SG (headers_sent ) && (!check_cookies || PS (use_cookies ))) {
1532+ char error_msg [256 ];
1533+ snprintf (error_msg , sizeof (error_msg ), "Session %s cannot be changed after headers have already been sent" , setting_name );
1534+ php_session_headers_already_sent_error (E_WARNING , error_msg );
1535+
1536+ return false;
1537+ }
1538+
1539+ return true;
1540+ }
1541+
1542+ static void try_find_session_id_in_cookies (void )
1543+ {
1544+ zval * cookie_data , * potential_session_id ;
1545+
1546+ if (!PS (use_cookies ) || PS (id )) {
1547+ return ;
1548+ }
1549+
1550+ cookie_data = zend_hash_str_find (& EG (symbol_table ), ZEND_STRL ("_COOKIE" ));
1551+ if (!cookie_data ) {
1552+ return ;
1553+ }
1554+
1555+ ZVAL_DEREF (cookie_data );
1556+ if (Z_TYPE_P (cookie_data ) != IS_ARRAY ) {
1557+ return ;
1558+ }
1559+
1560+ potential_session_id = zend_hash_find (Z_ARRVAL_P (cookie_data ), PS (session_name ));
1561+ if (potential_session_id ) {
1562+ proposed_session_id_to_session_id (potential_session_id );
1563+ PS (send_cookie ) = 0 ;
1564+ PS (define_sid ) = 0 ;
1565+ }
14691566}
14701567
1471- static void ppid2sid (zval * ppid ) {
1472- ZVAL_DEREF (ppid );
1473- if (Z_TYPE_P (ppid ) == IS_STRING ) {
1474- PS (id ) = zend_string_copy (Z_STR_P (ppid ));
1568+ static void proposed_session_id_to_session_id (zval * proposed_session_id ) {
1569+ ZVAL_DEREF (proposed_session_id );
1570+ if (Z_TYPE_P (proposed_session_id ) == IS_STRING ) {
1571+ PS (id ) = zend_string_copy (Z_STR_P (proposed_session_id ));
14751572 PS (send_cookie ) = 0 ;
14761573 } else {
14771574 PS (id ) = NULL ;
@@ -1483,7 +1580,7 @@ static void ppid2sid(zval *ppid) {
14831580PHPAPI zend_result php_session_reset_id (void )
14841581{
14851582 int module_number = PS (module_number );
1486- zval * sid , * data , * ppid ;
1583+ zval * sid , * data , * potential_session_id ;
14871584 bool apply_trans_sid ;
14881585
14891586 if (!PS (id )) {
@@ -1545,8 +1642,8 @@ PHPAPI zend_result php_session_reset_id(void)
15451642 (data = zend_hash_str_find (& EG (symbol_table ), ZEND_STRL ("_COOKIE" )))) {
15461643 ZVAL_DEREF (data );
15471644 if (Z_TYPE_P (data ) == IS_ARRAY &&
1548- (ppid = zend_hash_find (Z_ARRVAL_P (data ), PS (session_name )))) {
1549- ZVAL_DEREF (ppid );
1645+ (potential_session_id = zend_hash_find (Z_ARRVAL_P (data ), PS (session_name )))) {
1646+ ZVAL_DEREF (potential_session_id );
15501647 apply_trans_sid = 0 ;
15511648 }
15521649 }
@@ -1561,8 +1658,6 @@ PHPAPI zend_result php_session_reset_id(void)
15611658
15621659PHPAPI zend_result php_session_start (void )
15631660{
1564- zval * ppid ;
1565- zval * data ;
15661661 char * value ;
15671662
15681663 switch (PS (session_status )) {
@@ -1607,37 +1702,13 @@ PHPAPI zend_result php_session_start(void)
16071702 */
16081703
16091704 if (!PS (id )) {
1610- if (PS (use_cookies ) && (data = zend_hash_str_find (& EG (symbol_table ), ZEND_STRL ("_COOKIE" )))) {
1611- ZVAL_DEREF (data );
1612- if (Z_TYPE_P (data ) == IS_ARRAY && (ppid = zend_hash_find (Z_ARRVAL_P (data ), PS (session_name )))) {
1613- ppid2sid (ppid );
1614- PS (send_cookie ) = 0 ;
1615- PS (define_sid ) = 0 ;
1616- }
1617- }
1618- /* Initialize session ID from non cookie values */
1705+ try_find_session_id_in_cookies ();
1706+
16191707 if (!PS (use_only_cookies )) {
1620- if (!PS (id ) && (data = zend_hash_str_find (& EG (symbol_table ), ZEND_STRL ("_GET" )))) {
1621- ZVAL_DEREF (data );
1622- if (Z_TYPE_P (data ) == IS_ARRAY && (ppid = zend_hash_find (Z_ARRVAL_P (data ), PS (session_name )))) {
1623- ppid2sid (ppid );
1624- }
1625- }
1626- if (!PS (id ) && (data = zend_hash_str_find (& EG (symbol_table ), ZEND_STRL ("_POST" )))) {
1627- ZVAL_DEREF (data );
1628- if (Z_TYPE_P (data ) == IS_ARRAY && (ppid = zend_hash_find (Z_ARRVAL_P (data ), PS (session_name )))) {
1629- ppid2sid (ppid );
1630- }
1631- }
1632- /* Check whether the current request was referred to by
1633- * an external site which invalidates the previously found id. */
1634- if (PS (id ) && PS (extern_referer_chk )[0 ] != '\0' &&
1635- !Z_ISUNDEF (PG (http_globals )[TRACK_VARS_SERVER ]) &&
1636- (data = zend_hash_str_find (Z_ARRVAL (PG (http_globals )[TRACK_VARS_SERVER ]), ZEND_STRL ("HTTP_REFERER" ))) &&
1637- Z_TYPE_P (data ) == IS_STRING &&
1638- Z_STRLEN_P (data ) != 0 &&
1639- strstr (Z_STRVAL_P (data ), PS (extern_referer_chk )) == NULL
1640- ) {
1708+ try_find_session_id_in_global (ZEND_STRL ("_GET" ));
1709+ try_find_session_id_in_global (ZEND_STRL ("_POST" ));
1710+
1711+ if (should_invalidate_session_for_external_referer ()) {
16411712 zend_string_release_ex (PS (id ), 0 );
16421713 PS (id ) = NULL ;
16431714 }
@@ -1923,13 +1994,7 @@ PHP_FUNCTION(session_name)
19231994 RETURN_THROWS ();
19241995 }
19251996
1926- if (name && PS (session_status ) == php_session_active ) {
1927- php_session_session_already_started_error (E_WARNING , "Session name cannot be changed when a session is active" );
1928- RETURN_FALSE ;
1929- }
1930-
1931- if (name && SG (headers_sent )) {
1932- php_session_headers_already_sent_error (E_WARNING , "Session name cannot be changed after headers have already been sent" );
1997+ if (name && !php_can_change_session_setting ("name" , false)) {
19331998 RETURN_FALSE ;
19341999 }
19352000
@@ -1952,13 +2017,7 @@ PHP_FUNCTION(session_module_name)
19522017 RETURN_THROWS ();
19532018 }
19542019
1955- if (name && PS (session_status ) == php_session_active ) {
1956- php_session_session_already_started_error (E_WARNING , "Session save handler module cannot be changed when a session is active" );
1957- RETURN_FALSE ;
1958- }
1959-
1960- if (name && SG (headers_sent )) {
1961- php_session_headers_already_sent_error (E_WARNING , "Session save handler module cannot be changed after headers have already been sent" );
2020+ if (name && !php_can_change_session_setting ("save handler module" , false)) {
19622021 RETURN_FALSE ;
19632022 }
19642023
@@ -2227,13 +2286,7 @@ PHP_FUNCTION(session_save_path)
22272286 RETURN_THROWS ();
22282287 }
22292288
2230- if (name && PS (session_status ) == php_session_active ) {
2231- php_session_session_already_started_error (E_WARNING , "Session save path cannot be changed when a session is active" );
2232- RETURN_FALSE ;
2233- }
2234-
2235- if (name && SG (headers_sent )) {
2236- php_session_headers_already_sent_error (E_WARNING , "Session save path cannot be changed after headers have already been sent" );
2289+ if (name && !php_can_change_session_setting ("save path" , false)) {
22372290 RETURN_FALSE ;
22382291 }
22392292
@@ -2255,13 +2308,7 @@ PHP_FUNCTION(session_id)
22552308 RETURN_THROWS ();
22562309 }
22572310
2258- if (name && PS (session_status ) == php_session_active ) {
2259- php_session_session_already_started_error (E_WARNING , "Session ID cannot be changed when a session is active" );
2260- RETURN_FALSE ;
2261- }
2262-
2263- if (name && PS (use_cookies ) && SG (headers_sent )) {
2264- php_session_headers_already_sent_error (E_WARNING , "Session ID cannot be changed after headers have already been sent" );
2311+ if (name && !php_can_change_session_setting ("ID" , true)) {
22652312 RETURN_FALSE ;
22662313 }
22672314
@@ -2962,24 +3009,24 @@ static PHP_MSHUTDOWN_FUNCTION(session)
29623009
29633010static PHP_MINFO_FUNCTION (session )
29643011{
2965- const ps_module * * mod ;
2966- ps_serializer * ser ;
3012+ const ps_module * * current_save_handler ;
3013+ ps_serializer * current_serializer ;
29673014 smart_str save_handlers = {0 };
29683015 smart_str ser_handlers = {0 };
2969- int i ;
3016+ int handler_index ;
29703017
2971- /* Get save handlers */
2972- for (i = 0 , mod = ps_modules ; i < MAX_MODULES ; i ++ , mod ++ ) {
2973- if (* mod && (* mod )-> s_name ) {
2974- smart_str_appends (& save_handlers , (* mod )-> s_name );
3018+ /* Collect names of all available save handlers */
3019+ for (handler_index = 0 , current_save_handler = ps_modules ; handler_index < MAX_MODULES ; handler_index ++ , current_save_handler ++ ) {
3020+ if (* current_save_handler && (* current_save_handler )-> s_name ) {
3021+ smart_str_appends (& save_handlers , (* current_save_handler )-> s_name );
29753022 smart_str_appendc (& save_handlers , ' ' );
29763023 }
29773024 }
29783025
2979- /* Get serializer handlers */
2980- for (i = 0 , ser = ps_serializers ; i < MAX_SERIALIZERS ; i ++ , ser ++ ) {
2981- if (ser -> name ) {
2982- smart_str_appends (& ser_handlers , ser -> name );
3026+ /* Collect names of all available serializers */
3027+ for (handler_index = 0 , current_serializer = ps_serializers ; handler_index < MAX_SERIALIZERS ; handler_index ++ , current_serializer ++ ) {
3028+ if (current_serializer -> name ) {
3029+ smart_str_appends (& ser_handlers , current_serializer -> name );
29833030 smart_str_appendc (& ser_handlers , ' ' );
29843031 }
29853032 }
@@ -3019,16 +3066,16 @@ static const zend_module_dep session_deps[] = {
30193066
30203067static bool early_find_sid_in (zval * dest , int where , php_session_rfc1867_progress * progress )
30213068{
3022- zval * ppid ;
3069+ zval * potential_session_id ;
30233070
30243071 if (Z_ISUNDEF (PG (http_globals )[where ])) {
30253072 return 0 ;
30263073 }
30273074
3028- if ((ppid = zend_hash_find (Z_ARRVAL (PG (http_globals )[where ]), PS (session_name )))
3029- && Z_TYPE_P (ppid ) == IS_STRING ) {
3075+ if ((potential_session_id = zend_hash_find (Z_ARRVAL (PG (http_globals )[where ]), PS (session_name )))
3076+ && Z_TYPE_P (potential_session_id ) == IS_STRING ) {
30303077 zval_ptr_dtor (dest );
3031- ZVAL_COPY_DEREF (dest , ppid );
3078+ ZVAL_COPY_DEREF (dest , potential_session_id );
30323079 return 1 ;
30333080 }
30343081
0 commit comments