From d21ca0965c5889ac0d24d036496cc41399442be8 Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Sun, 2 Aug 2026 16:11:04 +0800 Subject: [PATCH 01/10] ext/readline: enhance test coverage --- .../tests/readline_cli_multiline_states.phpt | 32 +++++++++++++++++++ ext/readline/tests/readline_cli_pager.phpt | 22 +++++++++++++ ext/readline/tests/readline_cli_prompt.phpt | 25 +++++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 ext/readline/tests/readline_cli_multiline_states.phpt create mode 100644 ext/readline/tests/readline_cli_pager.phpt create mode 100644 ext/readline/tests/readline_cli_prompt.phpt diff --git a/ext/readline/tests/readline_cli_multiline_states.phpt b/ext/readline/tests/readline_cli_multiline_states.phpt new file mode 100644 index 000000000000..1020126031b9 --- /dev/null +++ b/ext/readline/tests/readline_cli_multiline_states.phpt @@ -0,0 +1,32 @@ +--TEST-- +Interactive shell: multiline input states +--EXTENSIONS-- +readline +--SKIPIF-- + +--FILE-- +outside- +--EXPECTF-- +%AInteractive shell%Asingle%Adouble%APAREN%Ablock%Acomment%Aattribute%Aoutside-%Ainside%A diff --git a/ext/readline/tests/readline_cli_pager.phpt b/ext/readline/tests/readline_cli_pager.phpt new file mode 100644 index 000000000000..79fbe37f7f73 --- /dev/null +++ b/ext/readline/tests/readline_cli_pager.phpt @@ -0,0 +1,22 @@ +--TEST-- +Interactive shell: output through cli.pager +--EXTENSIONS-- +readline +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +%Apager output%A diff --git a/ext/readline/tests/readline_cli_prompt.phpt b/ext/readline/tests/readline_cli_prompt.phpt new file mode 100644 index 000000000000..548fedbe0283 --- /dev/null +++ b/ext/readline/tests/readline_cli_prompt.phpt @@ -0,0 +1,25 @@ +--TEST-- +Interactive shell: custom prompt escape sequences +--EXTENSIONS-- +readline +--SKIPIF-- + +--FILE-- +-\`-\q-' . "\xC3\xA9" . '-`echo "dyn";`-x '; +$descriptorspec = [['pipe', 'r'], STDOUT, STDERR]; +$proc = proc_open("$php $ini -d " . escapeshellarg("cli.prompt=$prompt") . " -a", $descriptorspec, $pipes); +fwrite($pipes[0], "if (true) {\n"); +fwrite($pipes[0], "echo \"prompt body\n\";\n"); +fwrite($pipes[0], "}\n"); +fwrite($pipes[0], "quit\n"); +fclose($pipes[0]); +proc_close($proc); +?> +--EXPECTF-- +%AInteractive shell%Aprompt contains unsupported unicode characters%Adyn%Aprompt body%A From 0b4eaf3a5f458022fba3ca6de1c0eb7e3d487bf2 Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Sun, 2 Aug 2026 16:23:36 +0800 Subject: [PATCH 02/10] add tests for edge cases --- ext/readline/tests/readline_cli_multiline_states.phpt | 8 ++++---- ext/readline/tests/readline_cli_prompt.phpt | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ext/readline/tests/readline_cli_multiline_states.phpt b/ext/readline/tests/readline_cli_multiline_states.phpt index 1020126031b9..5e09b6647e90 100644 --- a/ext/readline/tests/readline_cli_multiline_states.phpt +++ b/ext/readline/tests/readline_cli_multiline_states.phpt @@ -15,15 +15,15 @@ $proc = proc_open("$php $ini -a", $descriptorspec, $pipes); fwrite($pipes[0], "\n"); fwrite($pipes[0], "# comment without ini assignment\n"); -fwrite($pipes[0], "echo 'single\n';\n"); -fwrite($pipes[0], "echo \"double\n\";\n"); +fwrite($pipes[0], "echo 'single \\\\ escape\n';\n"); +fwrite($pipes[0], "echo \"double \\\\ escape\n\";\n"); fwrite($pipes[0], "echo strtoupper(\n\"paren\"\n);\n"); fwrite($pipes[0], "if (true) {\necho \"block\n\";\n}\n"); +fwrite($pipes[0], "// line comment\n"); fwrite($pipes[0], "/*\n*/\necho \"comment\n\";\n"); fwrite($pipes[0], "#[AllowDynamicProperties]\nclass ReadlineCliCoverageClass {}\n"); fwrite($pipes[0], "echo \"attribute\n\";\n"); -fwrite($pipes[0], "?>outside-outside-\n-\`-\q-' . "\xC3\xA9" . '-`echo "dyn";`-x '; +$prompt = 'pre\\\\-\n-\t-\e-\v-\b-\>-\`-\q-' . "\xC3\xA9\xC3\xA9" . '-`echo "dyn";`-x '; $descriptorspec = [['pipe', 'r'], STDOUT, STDERR]; $proc = proc_open("$php $ini -d " . escapeshellarg("cli.prompt=$prompt") . " -a", $descriptorspec, $pipes); fwrite($pipes[0], "if (true) {\n"); From f5761225063d4dd6a9d7e094e4501ac195fa4b60 Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Sun, 2 Aug 2026 16:29:41 +0800 Subject: [PATCH 03/10] more tests --- .../tests/readline_cli_auto_prepend.phpt | 30 ++++++++++++++ .../readline_cli_completion_readline.phpt | 39 +++++++++++++++++++ .../tests/readline_cli_long_input.phpt | 22 +++++++++++ .../tests/readline_cli_multiline_states.phpt | 3 +- ext/readline/tests/readline_cli_prompt.phpt | 2 +- 5 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 ext/readline/tests/readline_cli_auto_prepend.phpt create mode 100644 ext/readline/tests/readline_cli_completion_readline.phpt create mode 100644 ext/readline/tests/readline_cli_long_input.phpt diff --git a/ext/readline/tests/readline_cli_auto_prepend.phpt b/ext/readline/tests/readline_cli_auto_prepend.phpt new file mode 100644 index 000000000000..71d4477a7cde --- /dev/null +++ b/ext/readline/tests/readline_cli_auto_prepend.phpt @@ -0,0 +1,30 @@ +--TEST-- +Interactive shell: auto_prepend_file is executed before input +--EXTENSIONS-- +readline +--SKIPIF-- + +--FILE-- + []); +PHP); + +$php = getenv('TEST_PHP_EXECUTABLE_ESCAPED'); +$ini = getenv('TEST_PHP_EXTRA_ARGS'); +$descriptorspec = [['pipe', 'r'], STDOUT, STDERR]; +$proc = proc_open("$php $ini -d auto_prepend_file=" . escapeshellarg($prepend) . " -a", $descriptorspec, $pipes); +fwrite($pipes[0], "echo READLINE_CLI_PREPENDED . \"\n\";\n"); +fwrite($pipes[0], "exit\n"); +fclose($pipes[0]); +proc_close($proc); +unlink($prepend); +?> +--EXPECTF-- +%AInteractive shell%Aprepended%Aok%A diff --git a/ext/readline/tests/readline_cli_completion_readline.phpt b/ext/readline/tests/readline_cli_completion_readline.phpt new file mode 100644 index 000000000000..fabcf59deba6 --- /dev/null +++ b/ext/readline/tests/readline_cli_completion_readline.phpt @@ -0,0 +1,39 @@ +--TEST-- +Interactive shell: default completion function +--EXTENSIONS-- +readline +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +%AInteractive shell%Avariable%Aprecision=3%Afunction%Aconstant%AReadlineCliCompletionClass%Aclass constant%Amethod%A diff --git a/ext/readline/tests/readline_cli_long_input.phpt b/ext/readline/tests/readline_cli_long_input.phpt new file mode 100644 index 000000000000..a74850aef2d4 --- /dev/null +++ b/ext/readline/tests/readline_cli_long_input.phpt @@ -0,0 +1,22 @@ +--TEST-- +Interactive shell: input buffer grows for long lines +--EXTENSIONS-- +readline +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +%AInteractive shell%A5000%A diff --git a/ext/readline/tests/readline_cli_multiline_states.phpt b/ext/readline/tests/readline_cli_multiline_states.phpt index 5e09b6647e90..aebbcc112542 100644 --- a/ext/readline/tests/readline_cli_multiline_states.phpt +++ b/ext/readline/tests/readline_cli_multiline_states.phpt @@ -18,6 +18,7 @@ fwrite($pipes[0], "# comment without ini assignment\n"); fwrite($pipes[0], "echo 'single \\\\ escape\n';\n"); fwrite($pipes[0], "echo \"double \\\\ escape\n\";\n"); fwrite($pipes[0], "echo strtoupper(\n\"paren\"\n);\n"); +fwrite($pipes[0], "echo 6 /\n2;\n"); fwrite($pipes[0], "if (true) {\necho \"block\n\";\n}\n"); fwrite($pipes[0], "// line comment\n"); fwrite($pipes[0], "/*\n*/\necho \"comment\n\";\n"); @@ -29,4 +30,4 @@ fclose($pipes[0]); proc_close($proc); ?> --EXPECTF-- -%AInteractive shell%Asingle%Adouble%APAREN%Ablock%Acomment%Aattribute%Aoutside-%Ainside%A +%AInteractive shell%Asingle%Adouble%APAREN%A3%Ablock%Acomment%Aattribute%Aoutside-%Ainside%A diff --git a/ext/readline/tests/readline_cli_prompt.phpt b/ext/readline/tests/readline_cli_prompt.phpt index e93b9acbe0b3..dd46ca362860 100644 --- a/ext/readline/tests/readline_cli_prompt.phpt +++ b/ext/readline/tests/readline_cli_prompt.phpt @@ -11,7 +11,7 @@ if (!function_exists('proc_open')) die('skip proc_open() not available'); -\`-\q-' . "\xC3\xA9\xC3\xA9" . '-`echo "dyn";`-x '; +$prompt = 'pre\\\\-\n-\t-\e-\v-\b-\>-\`-\q-' . "\xC3\xA9\xC3\xA9" . '-`echo "dyn";`-`-x '; $descriptorspec = [['pipe', 'r'], STDOUT, STDERR]; $proc = proc_open("$php $ini -d " . escapeshellarg("cli.prompt=$prompt") . " -a", $descriptorspec, $pipes); fwrite($pipes[0], "if (true) {\n"); From d7d2bd170dadf4672e653357f4686e71d2ff1320 Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Sun, 2 Aug 2026 19:26:50 +0800 Subject: [PATCH 04/10] [skip ci] Add NEWS and UPGRADING --- NEWS | 3 +++ UPGRADING | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/NEWS b/NEWS index 0d5b6300fc7a..425a48481a98 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,9 @@ PHP NEWS ReflectionAttribute::getShortName(). (Girgias) - Standard: + . Added the "filter.max_filter_count" stream context option for php://filter + URLs. Using more than 16 filters without configuring this option is now + deprecated. (Sjoerd Langkemper) . The following functions now raise a ValueError when the $filename argument contains NUL bytes: fileperms(), fileinode(), filesize(), fileowner(), filegroup(), fileatime(), filemtime(), filectime(), filetype(), diff --git a/UPGRADING b/UPGRADING index fd66c7e61180..135a61d0d205 100644 --- a/UPGRADING +++ b/UPGRADING @@ -363,6 +363,10 @@ PHP 8.6 UPGRADE NOTES internal API. It is controlled using error_mode, error_store and error_handler stream context options. RFC: https://wiki.php.net/rfc/stream_errors + . Added the "filter.max_filter_count" stream context option for php://filter + URLs. When set, opening the stream fails with a warning if the URL would + add more filters than the configured value. Negative values disable the + check. . Added stream socket context option so_reuseaddr that allows disabling address reuse (SO_REUSEADDR) and explicitly uses SO_EXCLUSIVEADDRUSE on Windows. @@ -413,6 +417,11 @@ PHP 8.6 UPGRADE NOTES is no longer maintained. RFC: https://wiki.php.net/rfc/eol-oniguruma +- Standard: + . Using more than 16 filters in a php://filter URL without configuring the + "filter.max_filter_count" stream context option now emits an E_DEPRECATED + warning. Use stream_filter_append() or configure this option explicitly. + ======================================== 5. Changed Functions ======================================== From 740bb6bc59a20a012b997015863707ce6ec426af Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Sun, 2 Aug 2026 19:27:51 +0800 Subject: [PATCH 05/10] [skip ci] Revert Add NEWS and UPGRADING This reverts commit d7d2bd170dadf4672e653357f4686e71d2ff1320. --- NEWS | 3 --- UPGRADING | 9 --------- 2 files changed, 12 deletions(-) diff --git a/NEWS b/NEWS index 425a48481a98..0d5b6300fc7a 100644 --- a/NEWS +++ b/NEWS @@ -21,9 +21,6 @@ PHP NEWS ReflectionAttribute::getShortName(). (Girgias) - Standard: - . Added the "filter.max_filter_count" stream context option for php://filter - URLs. Using more than 16 filters without configuring this option is now - deprecated. (Sjoerd Langkemper) . The following functions now raise a ValueError when the $filename argument contains NUL bytes: fileperms(), fileinode(), filesize(), fileowner(), filegroup(), fileatime(), filemtime(), filectime(), filetype(), diff --git a/UPGRADING b/UPGRADING index 135a61d0d205..fd66c7e61180 100644 --- a/UPGRADING +++ b/UPGRADING @@ -363,10 +363,6 @@ PHP 8.6 UPGRADE NOTES internal API. It is controlled using error_mode, error_store and error_handler stream context options. RFC: https://wiki.php.net/rfc/stream_errors - . Added the "filter.max_filter_count" stream context option for php://filter - URLs. When set, opening the stream fails with a warning if the URL would - add more filters than the configured value. Negative values disable the - check. . Added stream socket context option so_reuseaddr that allows disabling address reuse (SO_REUSEADDR) and explicitly uses SO_EXCLUSIVEADDRUSE on Windows. @@ -417,11 +413,6 @@ PHP 8.6 UPGRADE NOTES is no longer maintained. RFC: https://wiki.php.net/rfc/eol-oniguruma -- Standard: - . Using more than 16 filters in a php://filter URL without configuring the - "filter.max_filter_count" stream context option now emits an E_DEPRECATED - warning. Use stream_filter_append() or configure this option explicitly. - ======================================== 5. Changed Functions ======================================== From bd6c59b33009b1bfdc16f8ddaf4b4b54abf79ec1 Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Tue, 4 Aug 2026 10:35:40 +0800 Subject: [PATCH 06/10] feedback --- ext/readline/readline_cli.c | 4 +++- .../tests/readline_cli_completion_readline.phpt | 16 ++++++++-------- .../tests/readline_cli_multiline_states.phpt | 16 ++++++++-------- ext/readline/tests/readline_cli_pager.phpt | 6 +++--- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/ext/readline/readline_cli.c b/ext/readline/readline_cli.c index 3b2a08a15843..4aecb71e2b80 100644 --- a/ext/readline/readline_cli.c +++ b/ext/readline/readline_cli.c @@ -557,7 +557,9 @@ static char *cli_completion_generator(const char *text, int index) /* {{{ */ ZEND_FALLTHROUGH; case 2: case 3: - retval = cli_completion_generator_define(text, textlen, &cli_completion_state, ce ? &ce->constants_table : EG(zend_constants)); + retval = cli_completion_generator_define( + ce ? class_name_end + 2 : text, textlen, &cli_completion_state, + ce ? &ce->constants_table : EG(zend_constants)); if (retval || ce) { break; } diff --git a/ext/readline/tests/readline_cli_completion_readline.phpt b/ext/readline/tests/readline_cli_completion_readline.phpt index fabcf59deba6..a5a0de8035f0 100644 --- a/ext/readline/tests/readline_cli_completion_readline.phpt +++ b/ext/readline/tests/readline_cli_completion_readline.phpt @@ -15,19 +15,19 @@ $ini = getenv('TEST_PHP_EXTRA_ARGS'); putenv('TERM=VT100'); $code = <<<'PHP' -$readline_cli_completion_variable = "variable\n"; +$readline_cli_completion_variable = strtolower("VARIABLE_OK\n"); echo $readline_cli_completion_var ; #prec 3 -echo "precision=" . ini_get("precision") . "\n"; -function readline_cli_completion_function() { echo "function\n"; } +echo "precision_result=" . ini_get("precision") . "\n"; +function readline_cli_completion_function() { echo strtolower("FUNCTION_OK\n"); } readline_cli_completion_fun ); -define('READLINE_CLI_COMPLETION_CONSTANT', "constant\n"); +define('READLINE_CLI_COMPLETION_CONSTANT', strtolower("CONSTANT_OK\n")); echo READLINE_CLI_COMPLETION_CON ; class ReadlineCliCompletionClass { - public const COMPLETION_CLASS_CONSTANT = "class constant\n"; - public static function completionMethod() { echo "method\n"; } + public const COMPLETION_CLASS_CONSTANT = "CLASS" . "CONST_OK\n"; + public static function completionMethod() { echo strtolower("METHOD_OK\n"); } } -echo ReadlineCliCompletionCla ::class . "\n"; +echo "class_ok:" . ReadlineCliCompletionCla ::class . "\n"; echo ReadlineCliCompletionClass::COMPLETION_CLASS_CON ; ReadlineCliCompletionClass::completionM ); exit @@ -36,4 +36,4 @@ PHP; echo shell_exec("echo " . escapeshellarg($code) . " | $php $ini -a"); ?> --EXPECTF-- -%AInteractive shell%Avariable%Aprecision=3%Afunction%Aconstant%AReadlineCliCompletionClass%Aclass constant%Amethod%A +%AInteractive shell%Avariable_ok%Aprecision_result=3%Afunction_ok%Aconstant_ok%Aclass_ok:ReadlineCliCompletionClass%ACLASSCONST_OK%Amethod_ok%A diff --git a/ext/readline/tests/readline_cli_multiline_states.phpt b/ext/readline/tests/readline_cli_multiline_states.phpt index aebbcc112542..bac269bdaebf 100644 --- a/ext/readline/tests/readline_cli_multiline_states.phpt +++ b/ext/readline/tests/readline_cli_multiline_states.phpt @@ -15,19 +15,19 @@ $proc = proc_open("$php $ini -a", $descriptorspec, $pipes); fwrite($pipes[0], "\n"); fwrite($pipes[0], "# comment without ini assignment\n"); -fwrite($pipes[0], "echo 'single \\\\ escape\n';\n"); -fwrite($pipes[0], "echo \"double \\\\ escape\n\";\n"); +fwrite($pipes[0], "echo strtoupper('single \\\\ escape\n');\n"); +fwrite($pipes[0], "echo strtoupper(\"double \\\\ escape\n\");\n"); fwrite($pipes[0], "echo strtoupper(\n\"paren\"\n);\n"); -fwrite($pipes[0], "echo 6 /\n2;\n"); -fwrite($pipes[0], "if (true) {\necho \"block\n\";\n}\n"); +fwrite($pipes[0], "echo \"arithmetic=\", 6 /\n2 + 100;\n"); +fwrite($pipes[0], "if (true) {\necho strtoupper(\"block\n\");\n}\n"); fwrite($pipes[0], "// line comment\n"); -fwrite($pipes[0], "/*\n*/\necho \"comment\n\";\n"); +fwrite($pipes[0], "/*\n*/\necho strtoupper(\"comment\n\");\n"); fwrite($pipes[0], "#[AllowDynamicProperties]\nclass ReadlineCliCoverageClass {}\n"); -fwrite($pipes[0], "echo \"attribute\n\";\n"); -fwrite($pipes[0], "if (true) ?>outside-\noutside-\n --EXPECTF-- -%AInteractive shell%Asingle%Adouble%APAREN%A3%Ablock%Acomment%Aattribute%Aoutside-%Ainside%A +%AInteractive shell%ASINGLE%ADOUBLE%APAREN%Aarithmetic=103%ABLOCK%ACOMMENT%AATTRIBUTE%Aoutside-%AINSIDE%A diff --git a/ext/readline/tests/readline_cli_pager.phpt b/ext/readline/tests/readline_cli_pager.phpt index 79fbe37f7f73..fb9b22c83520 100644 --- a/ext/readline/tests/readline_cli_pager.phpt +++ b/ext/readline/tests/readline_cli_pager.phpt @@ -5,18 +5,18 @@ readline --SKIPIF-- --FILE-- --EXPECTF-- -%Apager output%A +%APAGER OUTPUT%A From f2f071926b7c2141264f1f859d5aa194e1bdb2c1 Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Tue, 4 Aug 2026 12:20:23 +0800 Subject: [PATCH 07/10] revert bug fix --- ext/readline/readline_cli.c | 4 +--- ext/readline/tests/readline_cli_completion_readline.phpt | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/ext/readline/readline_cli.c b/ext/readline/readline_cli.c index 4aecb71e2b80..3b2a08a15843 100644 --- a/ext/readline/readline_cli.c +++ b/ext/readline/readline_cli.c @@ -557,9 +557,7 @@ static char *cli_completion_generator(const char *text, int index) /* {{{ */ ZEND_FALLTHROUGH; case 2: case 3: - retval = cli_completion_generator_define( - ce ? class_name_end + 2 : text, textlen, &cli_completion_state, - ce ? &ce->constants_table : EG(zend_constants)); + retval = cli_completion_generator_define(text, textlen, &cli_completion_state, ce ? &ce->constants_table : EG(zend_constants)); if (retval || ce) { break; } diff --git a/ext/readline/tests/readline_cli_completion_readline.phpt b/ext/readline/tests/readline_cli_completion_readline.phpt index a5a0de8035f0..cd4cbe148346 100644 --- a/ext/readline/tests/readline_cli_completion_readline.phpt +++ b/ext/readline/tests/readline_cli_completion_readline.phpt @@ -24,11 +24,9 @@ readline_cli_completion_fun ); define('READLINE_CLI_COMPLETION_CONSTANT', strtolower("CONSTANT_OK\n")); echo READLINE_CLI_COMPLETION_CON ; class ReadlineCliCompletionClass { - public const COMPLETION_CLASS_CONSTANT = "CLASS" . "CONST_OK\n"; public static function completionMethod() { echo strtolower("METHOD_OK\n"); } } echo "class_ok:" . ReadlineCliCompletionCla ::class . "\n"; -echo ReadlineCliCompletionClass::COMPLETION_CLASS_CON ; ReadlineCliCompletionClass::completionM ); exit PHP; @@ -36,4 +34,4 @@ PHP; echo shell_exec("echo " . escapeshellarg($code) . " | $php $ini -a"); ?> --EXPECTF-- -%AInteractive shell%Avariable_ok%Aprecision_result=3%Afunction_ok%Aconstant_ok%Aclass_ok:ReadlineCliCompletionClass%ACLASSCONST_OK%Amethod_ok%A +%AInteractive shell%Avariable_ok%Aprecision_result=3%Afunction_ok%Aconstant_ok%Aclass_ok:ReadlineCliCompletionClass%Amethod_ok%A From 2435da99ea3dd17d91f2b96609f08259d80d4051 Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Tue, 4 Aug 2026 22:46:28 +0800 Subject: [PATCH 08/10] feedback --- .../tests/readline_cli_multiline_states.phpt | 18 +++++++-------- ext/readline/tests/readline_cli_pager.phpt | 11 ++++++++-- ext/readline/tests/readline_cli_prompt.phpt | 22 +++++++++++++++++-- 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/ext/readline/tests/readline_cli_multiline_states.phpt b/ext/readline/tests/readline_cli_multiline_states.phpt index bac269bdaebf..1aaea49ac963 100644 --- a/ext/readline/tests/readline_cli_multiline_states.phpt +++ b/ext/readline/tests/readline_cli_multiline_states.phpt @@ -14,20 +14,20 @@ $descriptorspec = [['pipe', 'r'], STDOUT, STDERR]; $proc = proc_open("$php $ini -a", $descriptorspec, $pipes); fwrite($pipes[0], "\n"); -fwrite($pipes[0], "# comment without ini assignment\n"); -fwrite($pipes[0], "echo strtoupper('single \\\\ escape\n');\n"); -fwrite($pipes[0], "echo strtoupper(\"double \\\\ escape\n\");\n"); +fwrite($pipes[0], "echo strtoupper('single \\' semi ; brace }\nend');\n"); +fwrite($pipes[0], "echo strtoupper(\"double \\\" semi ; brace }\nend\");\n"); fwrite($pipes[0], "echo strtoupper(\n\"paren\"\n);\n"); fwrite($pipes[0], "echo \"arithmetic=\", 6 /\n2 + 100;\n"); -fwrite($pipes[0], "if (true) {\necho strtoupper(\"block\n\");\n}\n"); -fwrite($pipes[0], "// line comment\n"); -fwrite($pipes[0], "/*\n*/\necho strtoupper(\"comment\n\");\n"); +fwrite($pipes[0], "if (true) {\necho strtoupper(\"block_body\n\");\n}\n"); +fwrite($pipes[0], "echo strtoupper(\n\"hash_comment\\n\"\n# ) ;\n);\n"); +fwrite($pipes[0], "echo strtoupper(\n\"slash_comment\\n\"\n// ) ;\n);\n"); +fwrite($pipes[0], "echo strtoupper(\n\"block_comment\\n\" /*\n) ;\n*/\n);\n"); fwrite($pipes[0], "#[AllowDynamicProperties]\nclass ReadlineCliCoverageClass {}\n"); -fwrite($pipes[0], "echo strtoupper(\"attribute\n\");\n"); -fwrite($pipes[0], "if (true) ?>outside-\ngetAttributes()[0]->getName()), \"\\n\";\n"); +fwrite($pipes[0], "if (true) ?>outside } );\n --EXPECTF-- -%AInteractive shell%ASINGLE%ADOUBLE%APAREN%Aarithmetic=103%ABLOCK%ACOMMENT%AATTRIBUTE%Aoutside-%AINSIDE%A +%AInteractive shell%ASINGLE%ADOUBLE%APAREN%Aarithmetic=103%ABLOCK_BODY%AHASH_COMMENT%ASLASH_COMMENT%ABLOCK_COMMENT%AALLOWDYNAMICPROPERTIES%AOUTSIDE_OK%A diff --git a/ext/readline/tests/readline_cli_pager.phpt b/ext/readline/tests/readline_cli_pager.phpt index fb9b22c83520..2d5309472324 100644 --- a/ext/readline/tests/readline_cli_pager.phpt +++ b/ext/readline/tests/readline_cli_pager.phpt @@ -5,6 +5,7 @@ readline --SKIPIF-- --FILE-- @@ -18,5 +19,11 @@ fwrite($pipes[0], "quit\n"); fclose($pipes[0]); proc_close($proc); ?> ---EXPECTF-- -%APAGER OUTPUT%A +--EXPECT-- +Interactive shell + +php > echo "pager output +php " "; +pager output +PAGER OUTPUT +php > quit diff --git a/ext/readline/tests/readline_cli_prompt.phpt b/ext/readline/tests/readline_cli_prompt.phpt index dd46ca362860..9e9b0846f263 100644 --- a/ext/readline/tests/readline_cli_prompt.phpt +++ b/ext/readline/tests/readline_cli_prompt.phpt @@ -15,11 +15,29 @@ $prompt = 'pre\\\\-\n-\t-\e-\v-\b-\>-\`-\q-' . "\xC3\xA9\xC3\xA9" . '-`echo "dyn $descriptorspec = [['pipe', 'r'], STDOUT, STDERR]; $proc = proc_open("$php $ini -d " . escapeshellarg("cli.prompt=$prompt") . " -a", $descriptorspec, $pipes); fwrite($pipes[0], "if (true) {\n"); -fwrite($pipes[0], "echo \"prompt body\n\";\n"); +fwrite($pipes[0], "echo strtoupper(\"prompt_body\\n\");\n"); fwrite($pipes[0], "}\n"); fwrite($pipes[0], "quit\n"); fclose($pipes[0]); proc_close($proc); ?> --EXPECTF-- -%AInteractive shell%Aprompt contains unsupported unicode characters%Adyn%Aprompt body%A +Interactive shell + + +Warning: prompt contains unsupported unicode characters in Unknown on line 0 +dynpre\- +- -%c-%d.%d.%s-php->-`-\q-????-dyn--x if (true) { + +Warning: prompt contains unsupported unicode characters in Unknown on line 0 +dynpre\- +- -%c-%d.%d.%s-php-{-`-\q-????-dyn--x echo strtoupper("prompt_body\n"); + +Warning: prompt contains unsupported unicode characters in Unknown on line 0 +dynpre\- +- -%c-%d.%d.%s-php-{-`-\q-????-dyn--x } + +Warning: prompt contains unsupported unicode characters in Unknown on line 0 +dynPROMPT_BODY +pre\- +- -%c-%d.%d.%s-php->-`-\q-????-dyn--x quit From ba8279277f868c16e145465ef219d3df39bf3b09 Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Tue, 4 Aug 2026 23:57:12 +0800 Subject: [PATCH 09/10] fix CI --- ext/readline/tests/readline_cli_prompt.phpt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/readline/tests/readline_cli_prompt.phpt b/ext/readline/tests/readline_cli_prompt.phpt index 9e9b0846f263..5d1fb3cd73f9 100644 --- a/ext/readline/tests/readline_cli_prompt.phpt +++ b/ext/readline/tests/readline_cli_prompt.phpt @@ -26,18 +26,18 @@ Interactive shell Warning: prompt contains unsupported unicode characters in Unknown on line 0 -dynpre\- -- -%c-%d.%d.%s-php->-`-\q-????-dyn--x if (true) { +pre\- +- -%c-%d.%d.%s-php->-`-\q-????-echodynif (true) { Warning: prompt contains unsupported unicode characters in Unknown on line 0 -dynpre\- -- -%c-%d.%d.%s-php-{-`-\q-????-dyn--x echo strtoupper("prompt_body\n"); +pre\- +- -%c-%d.%d.%s-php-{-`-\q-????-echodynecho strtoupper("prompt_body\n"); Warning: prompt contains unsupported unicode characters in Unknown on line 0 -dynpre\- -- -%c-%d.%d.%s-php-{-`-\q-????-dyn--x } +pre\- +- -%c-%d.%d.%s-php-{-`-\q-????-echodyn} Warning: prompt contains unsupported unicode characters in Unknown on line 0 -dynPROMPT_BODY +PROMPT_BODY pre\- -- -%c-%d.%d.%s-php->-`-\q-????-dyn--x quit +- -%c-%d.%d.%s-php->-`-\q-????-echodynquit From f1d0c73ab91a601929a07117f41305653233242c Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Wed, 5 Aug 2026 00:15:47 +0800 Subject: [PATCH 10/10] feedback --- ext/readline/tests/readline_cli_prompt.phpt | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ext/readline/tests/readline_cli_prompt.phpt b/ext/readline/tests/readline_cli_prompt.phpt index 5d1fb3cd73f9..ddb5296cf943 100644 --- a/ext/readline/tests/readline_cli_prompt.phpt +++ b/ext/readline/tests/readline_cli_prompt.phpt @@ -11,9 +11,9 @@ if (!function_exists('proc_open')) die('skip proc_open() not available'); -\`-\q-' . "\xC3\xA9\xC3\xA9" . '-`echo "dyn";`-`-x '; +$prompt = 'pre\\\\-\n-\t-\e-\v-\b-\>-\`-\q-' . "\xC3\xA9\xC3\xA9" . '-`echo \'dyn\';`-`-x '; $descriptorspec = [['pipe', 'r'], STDOUT, STDERR]; -$proc = proc_open("$php $ini -d " . escapeshellarg("cli.prompt=$prompt") . " -a", $descriptorspec, $pipes); +$proc = proc_open("$php $ini -d " . escapeshellarg("cli.prompt=\"$prompt\"") . " -a", $descriptorspec, $pipes); fwrite($pipes[0], "if (true) {\n"); fwrite($pipes[0], "echo strtoupper(\"prompt_body\\n\");\n"); fwrite($pipes[0], "}\n"); @@ -26,18 +26,18 @@ Interactive shell Warning: prompt contains unsupported unicode characters in Unknown on line 0 -pre\- -- -%c-%d.%d.%s-php->-`-\q-????-echodynif (true) { +dynpre\- +- -%c-%d.%d.%s-php->-`-\q-????-dyn--x if (true) { Warning: prompt contains unsupported unicode characters in Unknown on line 0 -pre\- -- -%c-%d.%d.%s-php-{-`-\q-????-echodynecho strtoupper("prompt_body\n"); +dynpre\- +- -%c-%d.%d.%s-php-{-`-\q-????-dyn--x echo strtoupper("prompt_body\n"); Warning: prompt contains unsupported unicode characters in Unknown on line 0 -pre\- -- -%c-%d.%d.%s-php-{-`-\q-????-echodyn} +dynpre\- +- -%c-%d.%d.%s-php-{-`-\q-????-dyn--x } Warning: prompt contains unsupported unicode characters in Unknown on line 0 -PROMPT_BODY +dynPROMPT_BODY pre\- -- -%c-%d.%d.%s-php->-`-\q-????-echodynquit +- -%c-%d.%d.%s-php->-`-\q-????-dyn--x quit