From 7355ed4c7d2a0e54467618c3f2979cef0d899a1d Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 25 Jan 2025 19:43:21 +0000 Subject: [PATCH 1/4] ext/session: start to implement GH-14019 --- ext/session/config.m4 | 46 +++++---- ext/session/mod_mm.c | 217 +++++++++++++----------------------------- ext/session/mod_mm.h | 2 +- 3 files changed, 88 insertions(+), 177 deletions(-) diff --git a/ext/session/config.m4 b/ext/session/config.m4 index 36cfdf10972ab..d3ceffde30dc4 100644 --- a/ext/session/config.m4 +++ b/ext/session/config.m4 @@ -14,10 +14,7 @@ PHP_ARG_WITH([mm], if test "$PHP_SESSION" != "no"; then PHP_PWRITE_TEST PHP_PREAD_TEST - PHP_NEW_EXTENSION([session], - [mod_user_class.c session.c mod_files.c mod_mm.c mod_user.c], - [$ext_shared],, - [-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1]) + SESSION_CFLAGS="-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1" PHP_ADD_EXTENSION_DEP(session, date) dnl https://bugs.php.net/53141 @@ -29,26 +26,27 @@ if test "$PHP_SESSION" != "no"; then [Define to 1 if the PHP extension 'session' is available.]) AS_VAR_IF([PHP_MM], [no],, [ - for i in $PHP_MM /usr/local /usr; do - AS_IF([test -f "$i/include/mm.h"], [MM_DIR=$i; break;]) - done - - AS_VAR_IF([MM_DIR],, - [AC_MSG_ERROR([Cannot find the 'mm' library, header file not found.])]) - - AS_VAR_IF([PHP_THREAD_SAFETY], [yes], [AC_MSG_ERROR(m4_text_wrap([ - The configure option '--with-mm' cannot be combined with '--enable-zts'. - The mm library is not thread-safe, and mod_mm.c refuses to compile. Either - remove the '--with-mm' option, or build without thread safety (remove the - '--enable-zts' option). - ]))]) - - PHP_ADD_LIBRARY_WITH_PATH([mm], - [$MM_DIR/$PHP_LIBDIR], - [SESSION_SHARED_LIBADD]) - PHP_ADD_INCLUDE([$MM_DIR/include]) + PKG_CHECK_MODULES([LIBGLIB], [glib-2.0 >= 2.0]) + + PHP_EVAL_INCLINE($[LIBGLIB_CFLAGS]) + PHP_EVAL_LIBLINE($[LIBGLIB_LIBS], [GLIB_SHARED_LIBADD]) + PHP_CHECK_LIBRARY([glib-2.0], [g_try_malloc], + [AC_DEFINE([HAVE_GLIB2], [1], + [Define to 1 if libglib-2.0 library has 'g_try_malloc' function.])], + [] + [$GLIB_LIBS]) + + SESSION_CFLAGS="$SESSION_CFLAGS $LIBGLIB_CFLAGS" + PHP_SUBST([GLIB_SHARED_LIBADD]) + + PHP_INSTALL_HEADERS([ext/session], [mod_mm.h]) - AC_DEFINE([HAVE_LIBMM], [1], - [Define to 1 if the system has the 'mm' library.]) + AC_DEFINE([HAVE_LIBGLIB], [1], + [Define to 1 if the system has the 'glib' library.]) ]) + + PHP_NEW_EXTENSION([session], + [mod_user_class.c session.c mod_files.c mod_mm.c mod_user.c], + [$ext_shared],, + [$SESSION_CFLAGS]) fi diff --git a/ext/session/mod_mm.c b/ext/session/mod_mm.c index 76de6035a315c..9ebfd3c980a16 100644 --- a/ext/session/mod_mm.c +++ b/ext/session/mod_mm.c @@ -16,10 +16,10 @@ #include "php.h" -#ifdef HAVE_LIBMM +#ifdef HAVE_LIBGLIB #include -#include +#include #include #include #include @@ -30,32 +30,31 @@ #include "mod_mm.h" #include "SAPI.h" -#ifdef ZTS -# error mm is not thread-safe -#endif - #define PS_MM_FILE "session_mm_" /* This list holds all data associated with one session. */ typedef struct ps_sd { - struct ps_sd *next; - uint32_t hv; /* hash value of key */ time_t ctime; /* time of last change */ void *data; size_t datalen; /* amount of valid data */ size_t alloclen; /* amount of allocated memory for data */ - zend_string *key; } ps_sd; typedef struct { - MM *mm; - ps_sd **hash; + GMappedFile *mm; + GHashTable *hash; uint32_t hash_max; uint32_t hash_cnt; pid_t owner; } ps_mm; +typedef struct { + ps_mm *data; + zend_long maxlifetime; + zend_long *nrdels; +} ps_timelimit; + static ps_mm *ps_mm_instance = NULL; #if 0 @@ -78,132 +77,47 @@ static inline uint32_t ps_sd_hash(const zend_string *data) return h; } -static void hash_split(ps_mm *data) -{ - uint32_t nmax; - ps_sd **nhash; - ps_sd **ohash, **ehash; - ps_sd *ps, *next; - - nmax = ((data->hash_max + 1) << 1) - 1; - nhash = mm_calloc(data->mm, nmax + 1, sizeof(*data->hash)); - - if (!nhash) { - /* no further memory to expand hash table */ - return; - } - - ehash = data->hash + data->hash_max + 1; - for (ohash = data->hash; ohash < ehash; ohash++) { - for (ps = *ohash; ps; ps = next) { - next = ps->next; - ps->next = nhash[ps->hv & nmax]; - nhash[ps->hv & nmax] = ps; - } - } - mm_free(data->mm, data->hash); - - data->hash = nhash; - data->hash_max = nmax; -} - static ps_sd *ps_sd_new(ps_mm *data, zend_string *key) { - uint32_t hv, slot; ps_sd *sd; - sd = mm_malloc(data->mm, sizeof(ps_sd) + ZSTR_LEN(key)); + sd = g_malloc(sizeof(ps_sd) + ZSTR_LEN(key)); if (!sd) { - php_error_docref(NULL, E_WARNING, "mm_malloc failed, avail %ld, err %s", mm_available(data->mm), mm_error()); + //php_error_docref(NULL, E_WARNING, "g_malloc failed, avail %ld, err %s", mm_available(data->mm), mm_error()); return NULL; } - hv = ps_sd_hash(key); - slot = hv & data->hash_max; - sd->ctime = 0; - sd->hv = hv; sd->data = NULL; sd->alloclen = sd->datalen = 0; - sd->key = zend_string_copy(key); - - sd->next = data->hash[slot]; - data->hash[slot] = sd; + g_hash_table_insert(data->hash, key, sd); data->hash_cnt++; - if (!sd->next) { - if (data->hash_cnt >= data->hash_max) { - hash_split(data); - } - } - - ps_mm_debug(("inserting %s(%p) into slot %d\n", ZSTR_VAL(key), sd, slot)); - return sd; } -static void ps_sd_destroy(ps_mm *data, ps_sd *sd) +static void ps_sd_destroy(ps_mm *data, zend_string *key, ps_sd *sd) { - uint32_t slot; - - slot = ps_sd_hash(sd->key) & data->hash_max; - - if (data->hash[slot] == sd) { - data->hash[slot] = sd->next; - } else { - ps_sd *prev; - - /* There must be some entry before the one we want to delete */ - for (prev = data->hash[slot]; prev->next != sd; prev = prev->next); - prev->next = sd->next; - } - data->hash_cnt--; if (sd->data) { - mm_free(data->mm, sd->data); + g_free(sd->data); } - zend_string_release(sd->key); - mm_free(data->mm, sd); + g_hash_table_remove(data->hash, key); } -static ps_sd *ps_sd_lookup(ps_mm *data, const zend_string *key, bool rw) +static ps_sd *ps_sd_lookup(ps_mm *data, const zend_string *key, bool _rw) { - uint32_t hv, slot; - ps_sd *ret, *prev; - - hv = ps_sd_hash(key); - slot = hv & data->hash_max; - - for (prev = NULL, ret = data->hash[slot]; ret; prev = ret, ret = ret->next) { - if (ret->hv == hv && zend_string_equals(ret->key, key)) { - break; - } - } - - if (ret && rw && ret != data->hash[slot]) { - /* Move the entry to the top of the linked list */ - if (prev) { - prev->next = ret->next; - } - - ret->next = data->hash[slot]; - data->hash[slot] = ret; - } - - ps_mm_debug(("lookup(%s): ret=%p,hv=%u,slot=%d\n", ZSTR_VAL(key), ret, hv, slot)); - - return ret; + return (ps_sd *)g_hash_table_lookup(data->hash, key); } static zend_result ps_mm_key_exists(ps_mm *data, const zend_string *key) { ps_sd *sd; - if (!key) { return FAILURE; } @@ -220,29 +134,58 @@ const ps_module ps_mod_mm = { #define PS_MM_DATA ps_mm *data = PS_GET_MOD_DATA() +static guint ps_mm_hash(gconstpointer key) { + return (guint)(zend_string_hash_val((zend_string *)key)); +} + +static gboolean ps_mm_key_equals(gconstpointer a, gconstpointer b) { + return zend_string_equals((const zend_string *)a, (const zend_string *)b); +} + static zend_result ps_mm_initialize(ps_mm *data, const char *path) { data->owner = getpid(); - data->mm = mm_create(0, path); + data->mm = g_mapped_file_new(path, TRUE, NULL); if (!data->mm) { return FAILURE; } data->hash_cnt = 0; data->hash_max = 511; - data->hash = mm_calloc(data->mm, data->hash_max + 1, sizeof(ps_sd *)); + data->hash = g_hash_table_new(ps_mm_hash, ps_mm_key_equals); if (!data->hash) { - mm_destroy(data->mm); + g_mapped_file_unref(data->mm); return FAILURE; } return SUCCESS; } -static void ps_mm_destroy(ps_mm *data) +static gboolean ps_mm_destroy_entry(gpointer key, gpointer val, gpointer _priv) { - ps_sd *sd, *next; + zend_string_release_ex((zend_string *)key, false); + ps_sd *sd = (ps_sd *)val; + g_free(sd); + return TRUE; +} + +static void ps_mm_timelimit(gpointer key, gpointer val, gpointer _priv) +{ + time_t limit; + time(&limit); + ps_timelimit *ps_tm = (ps_timelimit *)_priv; + + limit -= ps_tm->maxlifetime; + + ps_sd *sd = (ps_sd *)val; + if (sd->ctime < limit) { + ps_sd_destroy(ps_tm->data, (zend_string *)key, sd); + (*ps_tm->nrdels)++; + } +} +static void ps_mm_destroy(ps_mm *data) +{ /* This function is called during each module shutdown, but we must not release the shared memory pool, when an Apache child dies! */ @@ -250,15 +193,10 @@ static void ps_mm_destroy(ps_mm *data) return; } - for (int h = 0; h < data->hash_max + 1; h++) { - for (sd = data->hash[h]; sd; sd = next) { - next = sd->next; - ps_sd_destroy(data, sd); - } - } + g_hash_table_foreach_remove(data->hash, ps_mm_destroy_entry, NULL); - mm_free(data->mm, data->hash); - mm_destroy(data->mm); + g_hash_table_destroy(data->hash); + g_mapped_file_unref(data->mm); free(data); } @@ -270,7 +208,7 @@ PHP_MINIT_FUNCTION(ps_mm) char *ps_mm_path, euid[30]; zend_result ret; - ps_mm_instance = calloc(sizeof(*ps_mm_instance), 1); + ps_mm_instance = calloc(1, sizeof(*ps_mm_instance)); if (!ps_mm_instance) { return FAILURE; } @@ -344,8 +282,6 @@ PS_READ_FUNC(mm) ps_sd *sd; zend_result ret = FAILURE; - mm_lock(data->mm, MM_LOCK_RD); - /* If there is an ID and strict mode, verify existence */ if (PS(use_strict_mode) && ps_mm_key_exists(data, key) == FAILURE) { @@ -367,12 +303,10 @@ PS_READ_FUNC(mm) sd = ps_sd_lookup(data, PS(id), false); if (sd) { - *val = zend_string_init(sd->data, sd->datalen, 0); + *val = zend_string_init(sd->data, sd->datalen, false); ret = SUCCESS; } - mm_unlock(data->mm); - return ret; } @@ -391,14 +325,11 @@ PS_WRITE_FUNC(mm) if (sd) { if (val->len >= sd->alloclen) { - if (data->mm) { - mm_free(data->mm, sd->data); - } sd->alloclen = val->len + 1; - sd->data = mm_malloc(data->mm, sd->alloclen); + sd->data = g_realloc(sd->data, sd->alloclen); if (!sd->data) { - ps_sd_destroy(data, sd); + ps_sd_destroy(data, key, sd); php_error_docref(NULL, E_WARNING, "Cannot allocate new data segment"); sd = NULL; } @@ -410,8 +341,6 @@ PS_WRITE_FUNC(mm) } } - mm_unlock(data->mm); - return sd ? SUCCESS : FAILURE; } @@ -424,43 +353,27 @@ PS_DESTROY_FUNC(mm) sd = ps_sd_lookup(data, key, false); if (sd) { - ps_sd_destroy(data, sd); + ps_sd_destroy(data, key, sd); } - mm_unlock(data->mm); - return SUCCESS; } PS_GC_FUNC(mm) { PS_MM_DATA; - time_t limit; - ps_sd **ohash, **ehash; - ps_sd *sd, *next; *nrdels = 0; ps_mm_debug(("gc\n")); - time(&limit); - - limit -= maxlifetime; + ps_timelimit ps_tm; - mm_lock(data->mm, MM_LOCK_RW); + ps_tm.data = data; + ps_tm.maxlifetime = maxlifetime; + ps_tm.nrdels = nrdels; - ehash = data->hash + data->hash_max + 1; - for (ohash = data->hash; ohash < ehash; ohash++) { - for (sd = *ohash; sd; sd = next) { - next = sd->next; - if (sd->ctime < limit) { - ps_mm_debug(("purging %s\n", ZSTR_VAL(sd->key))); - ps_sd_destroy(data, sd); - (*nrdels)++; - } - } - } - mm_unlock(data->mm); + g_hash_table_foreach(data->hash, ps_mm_timelimit, &ps_tm); return *nrdels; } diff --git a/ext/session/mod_mm.h b/ext/session/mod_mm.h index b35e0b632ee91..758a5cc38e625 100644 --- a/ext/session/mod_mm.h +++ b/ext/session/mod_mm.h @@ -17,7 +17,7 @@ #ifndef MOD_MM_H #define MOD_MM_H -#ifdef HAVE_LIBMM +#ifdef HAVE_LIBGLIB #include "php_session.h" From a71f6c8813635d50e06509c967c00689fc82de6b Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 4 Jan 2026 08:05:03 +0000 Subject: [PATCH 2/4] using more glib2 and ZTS mutexes --- ext/session/mod_mm.c | 72 +++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 41 deletions(-) diff --git a/ext/session/mod_mm.c b/ext/session/mod_mm.c index 9ebfd3c980a16..f77a835738268 100644 --- a/ext/session/mod_mm.c +++ b/ext/session/mod_mm.c @@ -32,6 +32,10 @@ #define PS_MM_FILE "session_mm_" +#ifdef ZTS +MUTEX_T session_mm_lock; +#endif + /* This list holds all data associated with one session. */ typedef struct ps_sd { @@ -63,28 +67,14 @@ static ps_mm *ps_mm_instance = NULL; # define ps_mm_debug(a) #endif -static inline uint32_t ps_sd_hash(const zend_string *data) -{ - uint32_t h; - const char *data_char = ZSTR_VAL(data); - const char *e = ZSTR_VAL(data) + ZSTR_LEN(data); - - for (h = 2166136261U; data_char < e; ) { - h *= 16777619; - h ^= *data_char++; - } - - return h; -} - static ps_sd *ps_sd_new(ps_mm *data, zend_string *key) { ps_sd *sd; - sd = g_malloc(sizeof(ps_sd) + ZSTR_LEN(key)); + sd = g_try_malloc(sizeof(ps_sd) + ZSTR_LEN(key)); if (!sd) { - //php_error_docref(NULL, E_WARNING, "g_malloc failed, avail %ld, err %s", mm_available(data->mm), mm_error()); + php_error_docref(NULL, E_WARNING, "g_malloc failed"); return NULL; } @@ -110,24 +100,6 @@ static void ps_sd_destroy(ps_mm *data, zend_string *key, ps_sd *sd) g_hash_table_remove(data->hash, key); } -static ps_sd *ps_sd_lookup(ps_mm *data, const zend_string *key, bool _rw) -{ - return (ps_sd *)g_hash_table_lookup(data->hash, key); -} - -static zend_result ps_mm_key_exists(ps_mm *data, const zend_string *key) -{ - ps_sd *sd; - if (!key) { - return FAILURE; - } - sd = ps_sd_lookup(data, key, false); - if (sd) { - return SUCCESS; - } - return FAILURE; -} - const ps_module ps_mod_mm = { PS_MOD_SID(mm) }; @@ -244,6 +216,10 @@ PHP_MINIT_FUNCTION(ps_mm) return FAILURE; } +#ifdef ZTS + session_mm_lock = tsrm_mutex_alloc(); +#endif + php_session_register_module(&ps_mod_mm); return SUCCESS; } @@ -251,6 +227,10 @@ PHP_MINIT_FUNCTION(ps_mm) PHP_MSHUTDOWN_FUNCTION(ps_mm) { if (ps_mm_instance) { +#ifdef ZTS + tsrm_mutex_free(session_mm_lock); + session_mm_lock = NULL; +#endif ps_mm_destroy(ps_mm_instance); return SUCCESS; } @@ -284,7 +264,7 @@ PS_READ_FUNC(mm) /* If there is an ID and strict mode, verify existence */ if (PS(use_strict_mode) - && ps_mm_key_exists(data, key) == FAILURE) { + && g_hash_table_contains(data->hash, key) == FAILURE) { /* key points to PS(id), but cannot change here. */ if (key) { efree(PS(id)); @@ -301,7 +281,7 @@ PS_READ_FUNC(mm) PS(session_status) = php_session_active; } - sd = ps_sd_lookup(data, PS(id), false); + sd = g_hash_table_lookup(data->hash, PS(id)); if (sd) { *val = zend_string_init(sd->data, sd->datalen, false); ret = SUCCESS; @@ -315,9 +295,11 @@ PS_WRITE_FUNC(mm) PS_MM_DATA; ps_sd *sd; - mm_lock(data->mm, MM_LOCK_RW); +#ifdef ZTS + tsrm_mutex_lock(session_mm_lock); +#endif - sd = ps_sd_lookup(data, key, true); + sd = g_hash_table_lookup(data->hash, key); if (!sd) { sd = ps_sd_new(data, key); ps_mm_debug(("new entry for %s\n", ZSTR_VAL(key))); @@ -341,6 +323,9 @@ PS_WRITE_FUNC(mm) } } +#ifdef ZTS + tsrm_mutex_unlock(session_mm_lock); +#endif return sd ? SUCCESS : FAILURE; } @@ -349,13 +334,18 @@ PS_DESTROY_FUNC(mm) PS_MM_DATA; ps_sd *sd; - mm_lock(data->mm, MM_LOCK_RW); +#ifdef ZTS + tsrm_mutex_lock(session_mm_lock); +#endif - sd = ps_sd_lookup(data, key, false); + sd = g_hash_table_lookup(data->hash, key); if (sd) { ps_sd_destroy(data, key, sd); } +#ifdef ZTS + tsrm_mutex_unlock(session_mm_lock); +#endif return SUCCESS; } @@ -387,7 +377,7 @@ PS_CREATE_SID_FUNC(mm) do { sid = php_session_create_id((void **)&data); /* Check collision */ - if (ps_mm_key_exists(data, sid) == SUCCESS) { + if (g_hash_table_contains(data->hash, sid) == SUCCESS) { if (sid) { zend_string_release_ex(sid, 0); sid = NULL; From 79b987e0c51bd6d86b2c5bd9c813ace88f79514c Mon Sep 17 00:00:00 2001 From: David Carlier Date: Mon, 5 Jan 2026 20:40:16 +0000 Subject: [PATCH 3/4] use ZendMM --- ext/session/mod_mm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/session/mod_mm.c b/ext/session/mod_mm.c index f77a835738268..05e3fcd478f8f 100644 --- a/ext/session/mod_mm.c +++ b/ext/session/mod_mm.c @@ -169,7 +169,7 @@ static void ps_mm_destroy(ps_mm *data) g_hash_table_destroy(data->hash); g_mapped_file_unref(data->mm); - free(data); + efree(data); } PHP_MINIT_FUNCTION(ps_mm) @@ -180,13 +180,13 @@ PHP_MINIT_FUNCTION(ps_mm) char *ps_mm_path, euid[30]; zend_result ret; - ps_mm_instance = calloc(1, sizeof(*ps_mm_instance)); + ps_mm_instance = ecalloc(1, sizeof(*ps_mm_instance)); if (!ps_mm_instance) { return FAILURE; } if (!(euid_len = slprintf(euid, sizeof(euid), "%d", geteuid()))) { - free(ps_mm_instance); + efree(ps_mm_instance); ps_mm_instance = NULL; return FAILURE; } From d29d438dddacc2d8749c7f786efffe131a181394 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 10 Jan 2026 15:47:04 +0000 Subject: [PATCH 4/4] arnaud feedback --- ext/session/mod_mm.c | 66 +++++++++---------------------------------- ext/session/session.c | 6 ++-- 2 files changed, 16 insertions(+), 56 deletions(-) diff --git a/ext/session/mod_mm.c b/ext/session/mod_mm.c index 05e3fcd478f8f..22398e667c51a 100644 --- a/ext/session/mod_mm.c +++ b/ext/session/mod_mm.c @@ -46,10 +46,7 @@ typedef struct ps_sd { } ps_sd; typedef struct { - GMappedFile *mm; GHashTable *hash; - uint32_t hash_max; - uint32_t hash_cnt; pid_t owner; } ps_mm; @@ -84,15 +81,11 @@ static ps_sd *ps_sd_new(ps_mm *data, zend_string *key) g_hash_table_insert(data->hash, key, sd); - data->hash_cnt++; - return sd; } static void ps_sd_destroy(ps_mm *data, zend_string *key, ps_sd *sd) { - data->hash_cnt--; - if (sd->data) { g_free(sd->data); } @@ -114,19 +107,12 @@ static gboolean ps_mm_key_equals(gconstpointer a, gconstpointer b) { return zend_string_equals((const zend_string *)a, (const zend_string *)b); } -static zend_result ps_mm_initialize(ps_mm *data, const char *path) +static zend_result ps_mm_initialize(ps_mm *data) { data->owner = getpid(); - data->mm = g_mapped_file_new(path, TRUE, NULL); - if (!data->mm) { - return FAILURE; - } - - data->hash_cnt = 0; - data->hash_max = 511; data->hash = g_hash_table_new(ps_mm_hash, ps_mm_key_equals); if (!data->hash) { - g_mapped_file_unref(data->mm); + php_error_docref(NULL, E_WARNING, "hash table created failed"); return FAILURE; } @@ -168,50 +154,18 @@ static void ps_mm_destroy(ps_mm *data) g_hash_table_foreach_remove(data->hash, ps_mm_destroy_entry, NULL); g_hash_table_destroy(data->hash); - g_mapped_file_unref(data->mm); - efree(data); + pefree(data, true); } PHP_MINIT_FUNCTION(ps_mm) { - size_t save_path_len = ZSTR_LEN(PS(save_path)); - size_t mod_name_len = strlen(sapi_module.name); - size_t euid_len; - char *ps_mm_path, euid[30]; - zend_result ret; - - ps_mm_instance = ecalloc(1, sizeof(*ps_mm_instance)); + ps_mm_instance = pecalloc(1, sizeof(*ps_mm_instance), true); if (!ps_mm_instance) { return FAILURE; } - if (!(euid_len = slprintf(euid, sizeof(euid), "%d", geteuid()))) { - efree(ps_mm_instance); - ps_mm_instance = NULL; - return FAILURE; - } - - /* Directory + '/' + File + Module Name + Effective UID + \0 */ - ps_mm_path = emalloc(save_path_len + 1 + (sizeof(PS_MM_FILE) - 1) + mod_name_len + euid_len + 1); - - memcpy(ps_mm_path, ZSTR_VAL(PS(save_path)), save_path_len); - if (save_path_len && ZSTR_VAL(PS(save_path))[save_path_len - 1] != DEFAULT_SLASH) { - ps_mm_path[save_path_len] = DEFAULT_SLASH; - save_path_len++; - } - memcpy(ps_mm_path + save_path_len, PS_MM_FILE, sizeof(PS_MM_FILE) - 1); - save_path_len += sizeof(PS_MM_FILE) - 1; - memcpy(ps_mm_path + save_path_len, sapi_module.name, mod_name_len); - save_path_len += mod_name_len; - memcpy(ps_mm_path + save_path_len, euid, euid_len); - ps_mm_path[save_path_len + euid_len] = '\0'; - - ret = ps_mm_initialize(ps_mm_instance, ps_mm_path); - - efree(ps_mm_path); - - if (ret == FAILURE) { - free(ps_mm_instance); + if (ps_mm_initialize(ps_mm_instance) == FAILURE) { + pefree(ps_mm_instance, true); ps_mm_instance = NULL; return FAILURE; } @@ -376,6 +330,13 @@ PS_CREATE_SID_FUNC(mm) do { sid = php_session_create_id((void **)&data); + if (!sid) { + if (--maxfail < 0) { + return NULL; + } else { + continue; + } + } /* Check collision */ if (g_hash_table_contains(data->hash, sid) == SUCCESS) { if (sid) { @@ -387,7 +348,6 @@ PS_CREATE_SID_FUNC(mm) } } } while(!sid); - return sid; } diff --git a/ext/session/session.c b/ext/session/session.c index 8796005e9232f..5b9d4330216d4 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -50,7 +50,7 @@ #include "mod_files.h" #include "mod_user.h" -#ifdef HAVE_LIBMM +#ifdef HAVE_LIBGLIB #include "mod_mm.h" #endif @@ -2966,7 +2966,7 @@ static PHP_MINIT_FUNCTION(session) PS(session_status) = php_session_none; REGISTER_INI_ENTRIES(); -#ifdef HAVE_LIBMM +#ifdef HAVE_LIBGLIB PHP_MINIT(ps_mm) (INIT_FUNC_ARGS_PASSTHRU); #endif php_session_rfc1867_orig_callback = php_rfc1867_callback; @@ -2991,7 +2991,7 @@ static PHP_MSHUTDOWN_FUNCTION(session) { UNREGISTER_INI_ENTRIES(); -#ifdef HAVE_LIBMM +#ifdef HAVE_LIBGLIB PHP_MSHUTDOWN(ps_mm) (SHUTDOWN_FUNC_ARGS_PASSTHRU); #endif