[php-src] PHP-8.4: ext/readline: Fix class constant completion in readline interactive shell (#23218)

Weilin Du via GitHub <[email protected]>
Newsgroups gmane.comp.php.cvs.general
Message-ID <[email protected]>
Author: Weilin Du (LamentXU123)
Committer: GitHub (web-flow)
Pusher: LamentXU123
Date: 2026-08-12T22:04:57+08:00

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

ext/readline: Fix class constant completion in readline interactive shell (#23218)

Reference: https://github.com/php/php-src/pull/22994#discussion_r3708633591_ 

php -a class constant completion passed the full ClassName::PREFIX string to
the constant completion generator. And textlen had already been shortened to
the part after "::". This commit fixes this bug.

Co-authored-by: Ilia Alshanetsky <[email protected]>

Changed paths:
  A  ext/readline/tests/readline_cli_completion_class_constant.phpt
  M  NEWS
  M  ext/readline/readline_cli.c


Diff:

diff --git a/NEWS b/NEWS
index ffefe0d338ec..0d9e42792078 100644
--- a/NEWS
+++ b/NEWS
@@ -60,6 +60,9 @@ PHP                                                                        NEWS
   . Fixed segfault in ReflectionMethod::createFromMethodName() on an
     uninstantiable subclass. (iliaal)
 
+- Readline:
+  . Fixed class constant completion in the interactive shell. (Weilin Du)
+
 - Session:
   . Fix corruption in mod_mm. (ndossche)
   . Fixed bug GH-23043 (broken session id code can cause zend_mm_heap
diff --git a/ext/readline/readline_cli.c b/ext/readline/readline_cli.c
index ca4e8eb4fe9f..ff5caee9eb7d 100644
--- a/ext/readline/readline_cli.c
+++ b/ext/readline/readline_cli.c
@@ -531,6 +531,7 @@ static char *cli_completion_generator(const char *text, int index) /* {{{ */
 	} else {
 		char *lc_text;
 		const char *class_name_end;
+		const char *constant_text = text;
 		zend_string *class_name = NULL;
 		zend_class_entry *ce = NULL;
 
@@ -543,6 +544,7 @@ static char *cli_completion_generator(const char *text, int index) /* {{{ */
 				zend_string_release_ex(class_name, 0);
 				return NULL;
 			}
+			constant_text = class_name_end + 2;
 			lc_text = zend_str_tolower_dup(class_name_end + 2, textlen - 2 - class_name_len);
 			textlen -= (class_name_len + 2);
 		} else {
@@ -559,7 +561,7 @@ 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(constant_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_class_constant.phpt b/ext/readline/tests/readline_cli_completion_class_constant.phpt
new file mode 100644
index 000000000000..1d4e6228df01
--- /dev/null
+++ b/ext/readline/tests/readline_cli_completion_class_constant.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Interactive shell: class constant completion
+--EXTENSIONS--
+readline
+--SKIPIF--
+<?php
+if (READLINE_LIB !== "readline") die('skip readline only');
+if (!function_exists('shell_exec')) die('skip shell_exec() not available');
+?>
+--FILE--
+<?php
+$php = getenv('TEST_PHP_EXECUTABLE_ESCAPED');
+$ini = getenv('TEST_PHP_EXTRA_ARGS');
+
+putenv('TERM=VT100');
+putenv('INPUTRC=/dev/null');
+
+$code = <<<'PHP'
+class Foo {
+    public const FooBar = "wrong_constant\n";
+    public const Zed = "zed_ok\n";
+}
+echo strtoupper(Foo::Ze	);
+exit
+PHP;
+
+echo shell_exec("echo " . escapeshellarg($code) . " | $php $ini -a");
+?>
+--EXPECTF--
+%AInteractive shell%AZED_OK%A
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.