From 0cb8497fab5eef5d5d20541e32fbe8952e1a5264 Mon Sep 17 00:00:00 2001 From: lamentxu <1372449351@qq.com> Date: Tue, 21 Apr 2026 15:50:54 +0800 Subject: [PATCH 1/7] initial fix --- ext/standard/basic_functions.c | 5 ++++ .../general_functions/putenv_null_bytes.phpt | 25 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 ext/standard/tests/general_functions/putenv_null_bytes.phpt diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index ece7f1278f7e..367f8a9d4bd8 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -742,6 +742,11 @@ PHP_FUNCTION(putenv) Z_PARAM_STRING(setting, setting_len) ZEND_PARSE_PARAMETERS_END(); + if (memchr(setting, '\0', setting_len) != NULL) { + zend_argument_value_error(1, "must not contain any null bytes"); + RETURN_THROWS(); + } + if (setting_len == 0 || setting[0] == '=') { zend_argument_value_error(1, "must have a valid syntax"); RETURN_THROWS(); diff --git a/ext/standard/tests/general_functions/putenv_null_bytes.phpt b/ext/standard/tests/general_functions/putenv_null_bytes.phpt new file mode 100644 index 000000000000..b1d2ab358118 --- /dev/null +++ b/ext/standard/tests/general_functions/putenv_null_bytes.phpt @@ -0,0 +1,25 @@ +--TEST-- +putenv() rejects null bytes +--FILE-- +getMessage() . "\n"; + } +} + +var_dump(getenv($var_name)); + +?> +--EXPECT-- +putenv(): Argument #1 ($assignment) must not contain any null bytes +putenv(): Argument #1 ($assignment) must not contain any null bytes +bool(false) From b6cfe32af916e9f1361a22f060511a8fd59f7085 Mon Sep 17 00:00:00 2001 From: lamentxu <1372449351@qq.com> Date: Tue, 21 Apr 2026 16:00:24 +0800 Subject: [PATCH 2/7] NEWS and UPGRADING --- NEWS | 2 ++ UPGRADING | 2 ++ 2 files changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 73a2b3d6637c..a348f1fd12ec 100644 --- a/NEWS +++ b/NEWS @@ -170,6 +170,8 @@ PHP NEWS argument value is passed. (Girgias) . linkinfo() now raises a ValueError when the argument is an empty string. (Weilin Du) + . putenv() now raises a ValueError when the $assignment argument contains + null bytes. (Weilin Du) - Streams: . Added so_keepalive, tcp_keepidle, tcp_keepintvl and tcp_keepcnt stream diff --git a/UPGRADING b/UPGRADING index 9c3d5a2b29a7..c63d474ad505 100644 --- a/UPGRADING +++ b/UPGRADING @@ -88,6 +88,8 @@ PHP 8.6 UPGRADE NOTES argument value is passed. . array_change_key_case() now raises a ValueError when an invalid $case argument value is passed. + . putenv() now raises a ValueError when the $assignment argument contains + null bytes. . linkinfo() now raises a ValueError when the $path argument is empty. . pathinfo() now raises a ValueError when an invalid $flag argument value is passed. From 03be2a23d5c2cd555ea2b1e0f19872bc67b7fcfd Mon Sep 17 00:00:00 2001 From: lamentxu <1372449351@qq.com> Date: Tue, 21 Apr 2026 16:11:26 +0800 Subject: [PATCH 3/7] getenv --- NEWS | 2 ++ UPGRADING | 2 ++ ext/standard/basic_functions.c | 7 ++++++- .../general_functions/getenv_null_bytes.phpt | 17 +++++++++++++++++ 4 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/general_functions/getenv_null_bytes.phpt diff --git a/NEWS b/NEWS index a348f1fd12ec..9269fab0aebc 100644 --- a/NEWS +++ b/NEWS @@ -170,6 +170,8 @@ PHP NEWS argument value is passed. (Girgias) . linkinfo() now raises a ValueError when the argument is an empty string. (Weilin Du) + . getenv() now raises a ValueError when the $name argument contains null + bytes. (Weilin Du) . putenv() now raises a ValueError when the $assignment argument contains null bytes. (Weilin Du) diff --git a/UPGRADING b/UPGRADING index c63d474ad505..b6c3ea4f47a8 100644 --- a/UPGRADING +++ b/UPGRADING @@ -88,6 +88,8 @@ PHP 8.6 UPGRADE NOTES argument value is passed. . array_change_key_case() now raises a ValueError when an invalid $case argument value is passed. + . getenv() now raises a ValueError when the $name argument contains null + bytes. . putenv() now raises a ValueError when the $assignment argument contains null bytes. . linkinfo() now raises a ValueError when the $path argument is empty. diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 367f8a9d4bd8..5a10a11aa0a6 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -706,6 +706,11 @@ PHP_FUNCTION(getenv) return; } + if (UNEXPECTED(memchr(str, '\0', str_len) != NULL)) { + zend_argument_value_error(1, "must not contain any null bytes"); + RETURN_THROWS(); + } + if (!local_only) { /* SAPI method returns an emalloc()'d string */ char *ptr = sapi_getenv(str, str_len); @@ -742,7 +747,7 @@ PHP_FUNCTION(putenv) Z_PARAM_STRING(setting, setting_len) ZEND_PARSE_PARAMETERS_END(); - if (memchr(setting, '\0', setting_len) != NULL) { + if (UNEXPECTED(memchr(setting, '\0', setting_len) != NULL)) { zend_argument_value_error(1, "must not contain any null bytes"); RETURN_THROWS(); } diff --git a/ext/standard/tests/general_functions/getenv_null_bytes.phpt b/ext/standard/tests/general_functions/getenv_null_bytes.phpt new file mode 100644 index 000000000000..049232e48e3d --- /dev/null +++ b/ext/standard/tests/general_functions/getenv_null_bytes.phpt @@ -0,0 +1,17 @@ +--TEST-- +getenv() rejects null bytes +--FILE-- +getMessage() . "\n"; + } +} + +?> +--EXPECT-- +getenv(): Argument #1 ($name) must not contain any null bytes +getenv(): Argument #1 ($name) must not contain any null bytes From 6ede937b5bb7e997b277194f1970cda0539b847a Mon Sep 17 00:00:00 2001 From: lamentxu <1372449351@qq.com> Date: Tue, 21 Apr 2026 16:40:34 +0800 Subject: [PATCH 4/7] rewrite tests --- .../general_functions/getenv_null_bytes.phpt | 17 ----------------- ...=> putenv_and_getenv_reject_null_bytes.phpt} | 12 +++++++++++- 2 files changed, 11 insertions(+), 18 deletions(-) delete mode 100644 ext/standard/tests/general_functions/getenv_null_bytes.phpt rename ext/standard/tests/general_functions/{putenv_null_bytes.phpt => putenv_and_getenv_reject_null_bytes.phpt} (56%) diff --git a/ext/standard/tests/general_functions/getenv_null_bytes.phpt b/ext/standard/tests/general_functions/getenv_null_bytes.phpt deleted file mode 100644 index 049232e48e3d..000000000000 --- a/ext/standard/tests/general_functions/getenv_null_bytes.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -getenv() rejects null bytes ---FILE-- -getMessage() . "\n"; - } -} - -?> ---EXPECT-- -getenv(): Argument #1 ($name) must not contain any null bytes -getenv(): Argument #1 ($name) must not contain any null bytes diff --git a/ext/standard/tests/general_functions/putenv_null_bytes.phpt b/ext/standard/tests/general_functions/putenv_and_getenv_reject_null_bytes.phpt similarity index 56% rename from ext/standard/tests/general_functions/putenv_null_bytes.phpt rename to ext/standard/tests/general_functions/putenv_and_getenv_reject_null_bytes.phpt index b1d2ab358118..28a346237338 100644 --- a/ext/standard/tests/general_functions/putenv_null_bytes.phpt +++ b/ext/standard/tests/general_functions/putenv_and_getenv_reject_null_bytes.phpt @@ -1,8 +1,16 @@ --TEST-- -putenv() rejects null bytes +getenv() and putenv() reject null bytes --FILE-- getMessage() . "\n"; + } +} + $var_name = 'PHP_PUTENV_NUL_TEST'; foreach ([ @@ -20,6 +28,8 @@ var_dump(getenv($var_name)); ?> --EXPECT-- +getenv(): Argument #1 ($name) must not contain any null bytes +getenv(): Argument #1 ($name) must not contain any null bytes putenv(): Argument #1 ($assignment) must not contain any null bytes putenv(): Argument #1 ($assignment) must not contain any null bytes bool(false) From 96ea59b2073db15a03bc35707ad976894ffee859 Mon Sep 17 00:00:00 2001 From: lamentxu <1372449351@qq.com> Date: Tue, 21 Apr 2026 17:36:27 +0800 Subject: [PATCH 5/7] use Zend APIs --- ext/standard/basic_functions.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 5a10a11aa0a6..2730924f61ec 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -696,7 +696,7 @@ PHP_FUNCTION(getenv) ZEND_PARSE_PARAMETERS_START(0, 2) Z_PARAM_OPTIONAL - Z_PARAM_STRING_OR_NULL(str, str_len) + Z_PARAM_PATH_OR_NULL(str, str_len) Z_PARAM_BOOL(local_only) ZEND_PARSE_PARAMETERS_END(); @@ -706,11 +706,6 @@ PHP_FUNCTION(getenv) return; } - if (UNEXPECTED(memchr(str, '\0', str_len) != NULL)) { - zend_argument_value_error(1, "must not contain any null bytes"); - RETURN_THROWS(); - } - if (!local_only) { /* SAPI method returns an emalloc()'d string */ char *ptr = sapi_getenv(str, str_len); @@ -747,7 +742,7 @@ PHP_FUNCTION(putenv) Z_PARAM_STRING(setting, setting_len) ZEND_PARSE_PARAMETERS_END(); - if (UNEXPECTED(memchr(setting, '\0', setting_len) != NULL)) { + if (UNEXPECTED(zend_char_has_nul_byte(setting, setting_len))) { zend_argument_value_error(1, "must not contain any null bytes"); RETURN_THROWS(); } From aa088cb80f038fe1358ba9329642d5661d60db00 Mon Sep 17 00:00:00 2001 From: lamentxu <1372449351@qq.com> Date: Tue, 21 Apr 2026 17:49:15 +0800 Subject: [PATCH 6/7] use Z_PARAM_PATH --- ext/standard/basic_functions.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 2730924f61ec..5c6b1ce1d1d1 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -739,14 +739,9 @@ PHP_FUNCTION(putenv) #endif ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(setting, setting_len) + Z_PARAM_PATH(setting, setting_len) ZEND_PARSE_PARAMETERS_END(); - if (UNEXPECTED(zend_char_has_nul_byte(setting, setting_len))) { - zend_argument_value_error(1, "must not contain any null bytes"); - RETURN_THROWS(); - } - if (setting_len == 0 || setting[0] == '=') { zend_argument_value_error(1, "must have a valid syntax"); RETURN_THROWS(); From 39a0cca2d9b96f312ce79a5c3b3a42705fd24175 Mon Sep 17 00:00:00 2001 From: lamentxu <1372449351@qq.com> Date: Tue, 21 Apr 2026 20:19:08 +0800 Subject: [PATCH 7/7] [skip ci] UPGRADING and NEWS --- NEWS | 6 ++---- UPGRADING | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/NEWS b/NEWS index 9269fab0aebc..22762f98c2ca 100644 --- a/NEWS +++ b/NEWS @@ -170,10 +170,8 @@ PHP NEWS argument value is passed. (Girgias) . linkinfo() now raises a ValueError when the argument is an empty string. (Weilin Du) - . getenv() now raises a ValueError when the $name argument contains null - bytes. (Weilin Du) - . putenv() now raises a ValueError when the $assignment argument contains - null bytes. (Weilin Du) + . getenv() and putenv() now raises a ValueError when the first argument + contains null bytes. (Weilin Du) - Streams: . Added so_keepalive, tcp_keepidle, tcp_keepintvl and tcp_keepcnt stream diff --git a/UPGRADING b/UPGRADING index b6c3ea4f47a8..869e265af8a2 100644 --- a/UPGRADING +++ b/UPGRADING @@ -88,10 +88,8 @@ PHP 8.6 UPGRADE NOTES argument value is passed. . array_change_key_case() now raises a ValueError when an invalid $case argument value is passed. - . getenv() now raises a ValueError when the $name argument contains null - bytes. - . putenv() now raises a ValueError when the $assignment argument contains - null bytes. + . getenv() and putenv() now raises a ValueError when the first argument + contains null bytes. . linkinfo() now raises a ValueError when the $path argument is empty. . pathinfo() now raises a ValueError when an invalid $flag argument value is passed.