From d8030805eeabd541ee18e27211373e825703244d Mon Sep 17 00:00:00 2001 From: Gina Peter Bnayard Date: Tue, 13 Aug 2024 17:33:34 +0200 Subject: [PATCH 1/2] ext/standard/info.c: Throw ValueErrors on invalid inputs to php_uname() --- NEWS | 3 ++ UPGRADING | 1 + ext/standard/info.c | 19 ++++++++++-- .../general_functions/php_uname_error.phpt | 29 ++++++++++++------- 4 files changed, 39 insertions(+), 13 deletions(-) diff --git a/NEWS b/NEWS index 2c65e9799aba4..e5a758fc34f8a 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,9 @@ PHP NEWS - Core: . Exiting a namespace now clears seen symbols. (ilutov) +- Standard: + . php_uname() now throws ValueErrors on invalid inputs. (Girgias) + 15 Aug 2024, PHP 8.4.0beta1 - Core: diff --git a/UPGRADING b/UPGRADING index bcf95365538b9..350441c51c6ec 100644 --- a/UPGRADING +++ b/UPGRADING @@ -193,6 +193,7 @@ PHP 8.4 UPGRADE NOTES $enclosure arguments are not one byte long, or if the $escape is not one byte long or the empty string. This aligns the behaviour to be identical to that of fputcsv() and fgetcsv(). + . php_uname() now throws ValueErrors on invalid inputs. - Tidy: . Failures in the constructor now throw exceptions rather than emitting diff --git a/ext/standard/info.c b/ext/standard/info.c index 5e273588cb175..085f24c4c9074 100644 --- a/ext/standard/info.c +++ b/ext/standard/info.c @@ -660,6 +660,8 @@ static void php_get_windows_cpu(char *buf, size_t bufsize) PHPAPI zend_string *php_get_uname(char mode) { char *php_uname; + + ZEND_ASSERT(mode == 'a' || mode == 'm' || mode == 'n' || mode == 'r' || mode == 's' || mode == 'v'); #ifdef PHP_WIN32 char tmp_uname[256]; DWORD dwBuild=0; @@ -1313,15 +1315,26 @@ PHP_FUNCTION(php_sapi_name) /* {{{ Return information about the system PHP was built on */ PHP_FUNCTION(php_uname) { - char *mode = "a"; + char *mode_str = "a"; size_t modelen = sizeof("a")-1; ZEND_PARSE_PARAMETERS_START(0, 1) Z_PARAM_OPTIONAL - Z_PARAM_STRING(mode, modelen) + Z_PARAM_STRING(mode_str, modelen) ZEND_PARSE_PARAMETERS_END(); - RETURN_STR(php_get_uname(*mode)); + if (modelen != 1) { + zend_argument_value_error(1, "must be a single character"); + RETURN_THROWS(); + } + + char mode = *mode_str; + if (mode != 'a' && mode != 'm' && mode != 'n' && mode != 'r' && mode != 's' && mode != 'v') { + zend_argument_value_error(1, "must be one of \"a\", \"m\", \"n\", \"r\", \"s\", or \"v\""); + RETURN_THROWS(); + } + + RETURN_STR(php_get_uname(mode)); } /* }}} */ diff --git a/ext/standard/tests/general_functions/php_uname_error.phpt b/ext/standard/tests/general_functions/php_uname_error.phpt index 2f65ed587d36c..694ec19fb6b39 100644 --- a/ext/standard/tests/general_functions/php_uname_error.phpt +++ b/ext/standard/tests/general_functions/php_uname_error.phpt @@ -1,17 +1,26 @@ --TEST-- -Test php_uname() function - error conditions - pass function incorrect arguments +php_uname(): Invalid arguments --FILE-- getMessage(), PHP_EOL; +} +try { + var_dump(php_uname('test')); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump(php_uname('z')); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} ?> --EXPECT-- -*** Testing php_uname() - error test - --- Testing php_uname() function with invalid mode -- -bool(true) +ValueError: php_uname(): Argument #1 ($mode) must be a single character +ValueError: php_uname(): Argument #1 ($mode) must be a single character +ValueError: php_uname(): Argument #1 ($mode) must be one of "a", "m", "n", "r", "s", or "v" From 77bf9b76fd05ae93ffbbb2baaa2152223d5b083a Mon Sep 17 00:00:00 2001 From: Gina Peter Bnayard Date: Tue, 13 Aug 2024 22:30:22 +0200 Subject: [PATCH 2/2] Use an inline function to check for the valid mode --- ext/standard/info.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ext/standard/info.c b/ext/standard/info.c index 085f24c4c9074..2da58f3cccef6 100644 --- a/ext/standard/info.c +++ b/ext/standard/info.c @@ -656,12 +656,16 @@ static void php_get_windows_cpu(char *buf, size_t bufsize) /* }}} */ #endif +static inline bool php_is_valid_uname_mode(char mode) { + return mode == 'a' || mode == 'm' || mode == 'n' || mode == 'r' || mode == 's' || mode == 'v'; +} + /* {{{ php_get_uname */ PHPAPI zend_string *php_get_uname(char mode) { char *php_uname; - ZEND_ASSERT(mode == 'a' || mode == 'm' || mode == 'n' || mode == 'r' || mode == 's' || mode == 'v'); + ZEND_ASSERT(php_is_valid_uname_mode(mode)); #ifdef PHP_WIN32 char tmp_uname[256]; DWORD dwBuild=0; @@ -1329,7 +1333,7 @@ PHP_FUNCTION(php_uname) } char mode = *mode_str; - if (mode != 'a' && mode != 'm' && mode != 'n' && mode != 'r' && mode != 's' && mode != 'v') { + if (!php_is_valid_uname_mode(mode)) { zend_argument_value_error(1, "must be one of \"a\", \"m\", \"n\", \"r\", \"s\", or \"v\""); RETURN_THROWS(); }