From 93676a0425147de239f3758de6b0bce359dccdc6 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sun, 14 Sep 2025 11:42:59 +0100 Subject: [PATCH 1/2] ext/standard: Deprecate passing string which are not one byte long to ord() (#19440) RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_passing_string_which_are_not_one_byte_long_to_ord Co-authored-by: Niels Dossche <7771979+nielsdos@users.noreply.github.com> --- Zend/tests/constants/class_constants_005.phpt | 2 +- Zend/tests/nullsafe_operator/013.phpt | Bin 2832 -> 2909 bytes Zend/zend_compile.c | 16 ++++++++++------ ext/mbstring/tests/gb18030_2022_encoding.phpt | 2 +- ext/mbstring/tests/gb18030_encoding.phpt | 2 +- ext/standard/string.c | 9 +++++++++ .../get_html_translation_table_basic6.phpt | 2 +- ext/standard/tests/strings/ord_basic.phpt | 2 -- .../tests/strings/ord_not_1_byte.phpt | 15 +++++++++++++++ 9 files changed, 38 insertions(+), 12 deletions(-) create mode 100644 ext/standard/tests/strings/ord_not_1_byte.phpt diff --git a/Zend/tests/constants/class_constants_005.phpt b/Zend/tests/constants/class_constants_005.phpt index de53c2c0caa54..7accce13f208b 100644 --- a/Zend/tests/constants/class_constants_005.phpt +++ b/Zend/tests/constants/class_constants_005.phpt @@ -4,7 +4,7 @@ String interning during constants substitution opcache.enable_cli=0 --FILE-- diff --git a/Zend/tests/nullsafe_operator/013.phpt b/Zend/tests/nullsafe_operator/013.phpt index 540fcb734c3031a8158b6e01b4ac156399e18a56..ea35399548916013c54daecbfe675abdff91deaa 100644 GIT binary patch delta 38 ucmbOrc2{hJ9Q))=Y@&ii`DK|YnR)37iFpdCxdkPalR4PbH_NeqVg>*PsSOnX delta 12 TcmcaBHbHEI9Q)>M_D{?JA7ccG diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index aca73dbcc86d0..ad735c41acaff 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -4186,14 +4186,18 @@ static zend_result zend_compile_func_chr(znode *result, const zend_ast_list *arg } /* }}} */ -static zend_result zend_compile_func_ord(znode *result, zend_ast_list *args) /* {{{ */ +static zend_result zend_compile_func_ord(znode *result, const zend_ast_list *args) /* {{{ */ { - if (args->children == 1 && - args->child[0]->kind == ZEND_AST_ZVAL && - Z_TYPE_P(zend_ast_get_zval(args->child[0])) == IS_STRING) { - + zval *str; + if ( + args->children == 1 + && args->child[0]->kind == ZEND_AST_ZVAL + && (str = zend_ast_get_zval(args->child[0])) + && Z_TYPE_P(str) == IS_STRING + && Z_STRLEN_P(str) == 1 + ) { result->op_type = IS_CONST; - ZVAL_LONG(&result->u.constant, (unsigned char)Z_STRVAL_P(zend_ast_get_zval(args->child[0]))[0]); + ZVAL_LONG(&result->u.constant, (unsigned char)Z_STRVAL_P(str)[0]); return SUCCESS; } else { return FAILURE; diff --git a/ext/mbstring/tests/gb18030_2022_encoding.phpt b/ext/mbstring/tests/gb18030_2022_encoding.phpt index 6908e4fed75b6..178e0f38e6551 100644 --- a/ext/mbstring/tests/gb18030_2022_encoding.phpt +++ b/ext/mbstring/tests/gb18030_2022_encoding.phpt @@ -241,7 +241,7 @@ readGB18030_2022_ConversionTable(__DIR__ . '/data/GB18030-2022MappingTableBMP.tx findInvalidChars($toUnicode, $invalid, $truncated); function notFourByteCode($gb) { - return ((ord($gb) < 0x81 || ord($gb) > 0x84) && (ord($gb) < 0x90 || ord($gb) > 0xE3)) || + return ((ord($gb[0]) < 0x81 || ord($gb[0]) > 0x84) && (ord($gb[0]) < 0x90 || ord($gb[0]) > 0xE3)) || (strlen($gb) > 1 && (ord($gb[1]) < 0x30 || ord($gb[1]) > 0x39)); } diff --git a/ext/mbstring/tests/gb18030_encoding.phpt b/ext/mbstring/tests/gb18030_encoding.phpt index 52cb7ae54482f..6c51fe35f204f 100644 --- a/ext/mbstring/tests/gb18030_encoding.phpt +++ b/ext/mbstring/tests/gb18030_encoding.phpt @@ -240,7 +240,7 @@ $gb18030_BMP_Mappings = [ findInvalidChars($toUnicode, $invalid, $truncated); function notFourByteCode($gb) { - return ((ord($gb) < 0x81 || ord($gb) > 0x84) && (ord($gb) < 0x90 || ord($gb) > 0xE3)) || + return ((ord($gb[0]) < 0x81 || ord($gb[0]) > 0x84) && (ord($gb[0]) < 0x90 || ord($gb[0]) > 0xE3)) || (strlen($gb) > 1 && (ord($gb[1]) < 0x30 || ord($gb[1]) > 0x39)); } diff --git a/ext/standard/string.c b/ext/standard/string.c index fffd796d94a8f..8b76a179061cc 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -2655,6 +2655,15 @@ PHP_FUNCTION(ord) Z_PARAM_STR(str) ZEND_PARSE_PARAMETERS_END(); + if (UNEXPECTED(ZSTR_LEN(str) != 1)) { + if (ZSTR_LEN(str) == 0) { + php_error_docref(NULL, E_DEPRECATED, + "Providing an empty string is deprecated"); + } else { + php_error_docref(NULL, E_DEPRECATED, + "Providing a string that is not one byte long is deprecated. Use ord($str[0]) instead"); + } + } RETURN_LONG((unsigned char) ZSTR_VAL(str)[0]); } /* }}} */ diff --git a/ext/standard/tests/strings/get_html_translation_table_basic6.phpt b/ext/standard/tests/strings/get_html_translation_table_basic6.phpt index 1715b0852bfac..f4fadf7134c30 100644 --- a/ext/standard/tests/strings/get_html_translation_table_basic6.phpt +++ b/ext/standard/tests/strings/get_html_translation_table_basic6.phpt @@ -3,7 +3,7 @@ Test get_html_translation_table() function : basic functionality - HTML 5/Window --FILE-- +--EXPECTF-- +Deprecated: ord(): Providing an empty string is deprecated in %s on line 3 +int(0) + +Deprecated: ord(): Providing a string that is not one byte long is deprecated. Use ord($str[0]) instead in %s on line 4 +int(72) From 569b00332795867cea6332f4c414cd4ee17a0c83 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sun, 14 Sep 2025 11:46:13 +0100 Subject: [PATCH 2/2] Update NEWS/UPGRADING for ord() deprecation --- NEWS | 4 ++++ UPGRADING | 3 +++ 2 files changed, 7 insertions(+) diff --git a/NEWS b/NEWS index e7caa7cdb4ee8..7f52099e2e410 100644 --- a/NEWS +++ b/NEWS @@ -23,6 +23,10 @@ PHP NEWS - MBstring: . Updated Unicode data tables to Unicode 17.0. (Yuya Hamada) +- Standard: + . Passing strings which are not one byte long to ord() is now deprecated. + (Girgias) + - URI: . Fixed bug GH-19780 (InvalidUrlException should check $errors argument). (nielsdos) diff --git a/UPGRADING b/UPGRADING index cc9524996fe33..09675d91ee0ce 100644 --- a/UPGRADING +++ b/UPGRADING @@ -555,6 +555,9 @@ PHP 8.5 UPGRADE NOTES . Passing integers outside the interval [0, 255] to chr() is now deprecated. This is because a byte can only hold a value within this interval. RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_passing_integers_outside_the_interval_0_255_to_chr + . Passing a string which is not a single byte to ord() is now deprecated, + this is indicative of a bug. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_passing_string_which_are_not_one_byte_long_to_ord . Relying locally predefined variable $http_response_header is deprecated. Instead one should call the http_get_last_response_headers() function. RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_the_http_response_header_predefined_variable