[php-src] PHP-8.4: phpdbg: Fix off-by-one in phpdbg_safe_class_lookup() signal-safe class lookup (#22593)

Jorg Adam Sowa via GitHub <[email protected]>
Newsgroups gmane.comp.php.cvs.general
Message-ID <[email protected]>
Author: Jorg Adam Sowa (jorgsowa)
Committer: GitHub (web-flow)
Pusher: TimWolla
Date: 2026-07-04T20:07:49+02:00

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

phpdbg: Fix off-by-one in phpdbg_safe_class_lookup() signal-safe class lookup (#22593)

lc_length was set to name_length + 1, one past the actual lowercased
string length, so zend_hash_str_find_ptr() (which expects a strlen-style
length) never matched an existing class entry. This made class lookups
during phpdbg's signal-handler interruption path always fail silently.

Replaced the manual emalloc/tolower/efree dance with
zend_hash_str_find_ptr_lc(), which performs the lowercase copy and
lookup in one call and removes the surface for this class of bug.

Changed paths:
  M  NEWS
  M  sapi/phpdbg/phpdbg_utils.c


Diff:

diff --git a/NEWS b/NEWS
index 08a852a5a0d8..d950ce969fc1 100644
--- a/NEWS
+++ b/NEWS
@@ -44,6 +44,8 @@ PHP                                                                        NEWS
   . Fixed bug GH-17387 (Trivial crash in phpdbg lexer). (iliaal)
   . Fixed fleaked lowercased lookup keys in phpdbg_resolve_opline_break.
     (jorgsowa)
+  . Fixed off-by-one in phpdbg_safe_class_lookup() causing class lookups to
+    always fail during phpdbg's signal-safe interruption path. (jorgsowa)
 
 - Reflection:
   . Fixed bug GH-22324 (Ignore leading namespace separator in
diff --git a/sapi/phpdbg/phpdbg_utils.c b/sapi/phpdbg/phpdbg_utils.c
index 7465004e99ad..b3d3445b6272 100644
--- a/sapi/phpdbg/phpdbg_utils.c
+++ b/sapi/phpdbg/phpdbg_utils.c
@@ -397,29 +397,20 @@ PHPDBG_API void phpdbg_set_async_io(int fd) {
 
 int phpdbg_safe_class_lookup(const char *name, int name_length, zend_class_entry **ce) {
 	if (PHPDBG_G(flags) & PHPDBG_IN_SIGNAL_HANDLER) {
-		char *lc_name, *lc_free;
-		int lc_length;
-
 		if (name == NULL || !name_length) {
 			return FAILURE;
 		}
 
-		lc_free = lc_name = emalloc(name_length + 1);
-		zend_str_tolower_copy(lc_name, name, name_length);
-		lc_length = name_length + 1;
-
-		if (lc_name[0] == '\\') {
-			lc_name += 1;
-			lc_length -= 1;
+		if (name[0] == '\\') {
+			name += 1;
+			name_length -= 1;
 		}
 
 		phpdbg_try_access {
-			*ce = zend_hash_str_find_ptr(EG(class_table), lc_name, lc_length);
+			*ce = zend_hash_str_find_ptr_lc(EG(class_table), name, name_length);
 		} phpdbg_catch_access {
 			phpdbg_error("Could not fetch class %.*s, invalid data source", name_length, name);
 		} phpdbg_end_try_access();
-
-		efree(lc_free);
 	} else {
 		zend_string *str_name = zend_string_init(name, name_length, 0);
 		*ce = zend_lookup_class(str_name);
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.