From 19f94430d5c487bac4f26d406264d0fe543386e5 Mon Sep 17 00:00:00 2001 From: Jorg Adam Sowa Date: Fri, 3 Jul 2026 23:04:59 +0200 Subject: [PATCH 1/2] ext/session: reject null bytes in save_path and referer_check (#22578) session.cookie_path/cookie_domain/cache_limiter reject null bytes with a warning (OnUpdateSessionStr), but session.save_path silently failed with no diagnostic and session.referer_check didn't check at all. Align both with the existing OnUpdateSessionStr behavior. --- ext/session/session.c | 18 ++++++++++---- ...ion_save_path_referer_check_null_byte.phpt | 24 +++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 ext/session/tests/session_save_path_referer_check_null_byte.phpt diff --git a/ext/session/session.c b/ext/session/session.c index 1723acc4448c..dd968d453bda 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -647,12 +647,15 @@ static PHP_INI_MH(OnUpdateSaveDir) SESSION_CHECK_ACTIVE_STATE; SESSION_CHECK_OUTPUT_STATE; - /* Only do the open_basedir check at runtime */ - if (stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) { - if (zend_str_has_nul_byte(new_value)) { - return FAILURE; + if (zend_str_has_nul_byte(new_value)) { + if (stage != ZEND_INI_STAGE_DEACTIVATE) { + php_error_docref(NULL, E_WARNING, "\"%s\" must not contain null bytes", ZSTR_VAL(entry->name)); } + return FAILURE; + } + /* Only do the open_basedir check at runtime */ + if (stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) { /* we do not use zend_memrchr() since path can contain ; itself */ const char *p = strchr(ZSTR_VAL(new_value), ';'); if (p) { @@ -919,6 +922,13 @@ static PHP_INI_MH(OnUpdateRefererCheck) SESSION_CHECK_ACTIVE_STATE; SESSION_CHECK_OUTPUT_STATE; + if (zend_str_has_nul_byte(new_value)) { + if (stage != ZEND_INI_STAGE_DEACTIVATE) { + php_error_docref(NULL, E_WARNING, "\"%s\" must not contain null bytes", ZSTR_VAL(entry->name)); + } + return FAILURE; + } + if (ZSTR_LEN(new_value) != 0) { php_error_docref("session.configuration", E_DEPRECATED, "Usage of session.referer_check INI setting is deprecated"); } diff --git a/ext/session/tests/session_save_path_referer_check_null_byte.phpt b/ext/session/tests/session_save_path_referer_check_null_byte.phpt new file mode 100644 index 000000000000..9c4e87f2aa0a --- /dev/null +++ b/ext/session/tests/session_save_path_referer_check_null_byte.phpt @@ -0,0 +1,24 @@ +--TEST-- +session.save_path and session.referer_check must not contain null bytes +--EXTENSIONS-- +session +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Warning: ini_set(): "session.save_path" must not contain null bytes in %s on line %d +bool(false) + +Warning: ini_set(): "session.referer_check" must not contain null bytes in %s on line %d +bool(false) +Done From d673a1f56ddeb45faacfc27bcb5063942a26f60a Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Fri, 3 Jul 2026 21:30:16 -0400 Subject: [PATCH 2/2] Fix GH-22516: widen zend_mm srun free counter to cover bin 0 (#22530) The per-page free-slot counter in zend_mm_gc() is stored in a 9-bit field (ZEND_MM_SRUN_FREE_COUNTER_MASK, max 511). Bin 0 holds 512 slots, so a fully-free bin-0 page drives the counter to 512, which overflows the field and reads back as 0; the counter == bin_elements checks then never fire and the page is never reclaimed. Widen the field to 10 bits (0x03ff0000); bit 25 was unused and the write side already stays below it for every other bin. Bin 0 is only reachable where ZEND_MM_MIN_USEABLE_BIN_SIZE == 8 (32-bit, or heap-protection-disabled builds). Fixes GH-22516 --- Zend/zend_alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index d0f2b221b9a7..0b040743abf1 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -197,7 +197,7 @@ typedef zend_mm_bitset zend_mm_page_map[ZEND_MM_PAGE_MAP_LEN]; /* 64B */ #define ZEND_MM_SRUN_BIN_NUM_MASK 0x0000001f #define ZEND_MM_SRUN_BIN_NUM_OFFSET 0 -#define ZEND_MM_SRUN_FREE_COUNTER_MASK 0x01ff0000 +#define ZEND_MM_SRUN_FREE_COUNTER_MASK 0x03ff0000 #define ZEND_MM_SRUN_FREE_COUNTER_OFFSET 16 #define ZEND_MM_NRUN_OFFSET_MASK 0x01ff0000