[php-src] master: ext/session: reject null bytes in save_path and referer_check (#22578)

Jorg Adam Sowa via GitHub <[email protected]>
Newsgroups gmane.comp.php.cvs.general
Message-ID <[email protected]>
Author: Jorg Adam Sowa (jorgsowa)
Committer: GitHub (web-flow)
Pusher: Girgias
Date: 2026-07-03T22:04:59+01:00

Commit: https://github.com/php/php-src/commit/19f94430d5c487bac4f26d406264d0fe543386e5
Raw diff: https://github.com/php/php-src/commit/19f94430d5c487bac4f26d406264d0fe543386e5.diff

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.

Changed paths:
  A  ext/session/tests/session_save_path_referer_check_null_byte.phpt
  M  ext/session/session.c


Diff:

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--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+var_dump(ini_set('session.save_path', "/tmp\0evil"));
+var_dump(ini_set('session.referer_check', "example.com\0evil"));
+
+ob_end_flush();
+echo "Done";
+?>
+--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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.