Commit 2e564a747cc for php.net

commit 2e564a747ccd1836bb77e91a35a807e87765259c
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date:   Sun Jun 28 18:41:05 2026 -0400

    Fix GH-17387: crash on unterminated quote in phpdbg lexer

    In the NORMAL condition a lone unterminated quote matched no rule, so
    re2c backtracked to a zero-length GENERIC_ID accept. The rule body then
    computed yyleng - unescape_string(yytext) as 0 - N, underflowing size_t
    into a multi-gigabyte estrndup. Give a bare quote an explicit
    one-character accept so the cursor advances and unescape_string is never
    reached with a malformed token.

    Fixes GH-17387
    Closes GH-22506

diff --git a/NEWS b/NEWS
index 0f39334377e..531d6a334c0 100644
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,9 @@ PHP                                                                        NEWS
     copying, ArrayAccess, stream lookup, directory iteration and extraction.
     (Weilin Du)

+- PHPDBG:
+  . Fixed bug GH-17387 (Trivial crash in phpdbg lexer). (iliaal)
+
 - Reflection:
   . Fixed bug GH-22324 (Ignore leading namespace separator in
     ReflectionParameter::__construct()). (jorgsowa)
diff --git a/sapi/phpdbg/phpdbg_lexer.l b/sapi/phpdbg/phpdbg_lexer.l
index ba1423c5a4e..7c6315fc2a0 100644
--- a/sapi/phpdbg/phpdbg_lexer.l
+++ b/sapi/phpdbg/phpdbg_lexer.l
@@ -166,6 +166,13 @@ INPUT       ("\\"[#"']|["]("\\\\"|"\\"["]|[^\n\000"])*["]|[']("\\"[']|"\\\\"|[^\
 	return T_ID;
 }

+<NORMAL>["'] {
+	phpdbg_init_param(yylval, STR_PARAM);
+	yylval->str = estrndup(yytext, yyleng);
+	yylval->len = yyleng;
+	return T_ID;
+}
+
 <RAW>{INPUT} {
 	phpdbg_init_param(yylval, STR_PARAM);
 	yylval->str = estrdup(yytext);
diff --git a/sapi/phpdbg/tests/gh17387.phpt b/sapi/phpdbg/tests/gh17387.phpt
new file mode 100644
index 00000000000..af45fd4ba91
--- /dev/null
+++ b/sapi/phpdbg/tests/gh17387.phpt
@@ -0,0 +1,8 @@
+--TEST--
+GH-17387 (Trivial crash in phpdbg lexer)
+--PHPDBG--
+a';
+q
+--EXPECT--
+prompt> [The command "a" could not be found]
+prompt>