Skip to content

Commit e60aca4

Browse files
Cleanup and clarify session.c
1 parent fc467dc commit e60aca4

File tree

1 file changed

+145
-98
lines changed

1 file changed

+145
-98
lines changed

ext/session/session.c

Lines changed: 145 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ zend_class_entry *php_session_update_timestamp_iface_entry;
102102

103103
static zend_result php_session_send_cookie(void);
104104
static zend_result php_session_abort(void);
105+
static void ppid2sid(zval *proposed_session_id);
105106

106107
/* Initialized in MINIT, readonly otherwise. */
107108
static int my_module_number = 0;
@@ -369,7 +370,7 @@ PHPAPI zend_string *php_session_create_id(PS_CREATE_SID_ARGS)
369370
* ps_modules appropriately */
370371
PHPAPI 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

399400
static 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

417419
static zend_result php_session_initialize(void)
@@ -1441,37 +1443,132 @@ static zend_result php_session_send_cookie(void)
14411443

14421444
PHPAPI 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

14571459
PHPAPI 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)
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, strlen(global_name));
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+
ppid2sid(potential_session_id);
1518+
}
1519+
}
1520+
1521+
static bool 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, strlen(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, strlen(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+
ppid2sid(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 ppid2sid(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;
@@ -1561,8 +1658,6 @@ PHPAPI zend_result php_session_reset_id(void)
15611658

15621659
PHPAPI 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("_GET");
1709+
try_find_session_id_in_global("_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 && !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 && !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 && !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 && !can_change_session_setting("ID", true)) {
22652312
RETURN_FALSE;
22662313
}
22672314

@@ -2962,24 +3009,24 @@ static PHP_MSHUTDOWN_FUNCTION(session)
29623009

29633010
static 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

30203067
static 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

Comments
 (0)