[php-src] master: Zend: include() with a non-literal argument reads out of bounds with error_include_args=1.

David Carlier <[email protected]>
Newsgroups gmane.comp.php.cvs.general
Message-ID <[email protected]>
Author: David Carlier (devnexen)
Date: 2026-08-06T21:50:03+01:00

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

Zend: include() with a non-literal argument reads out of bounds with error_include_args=1.

Fix #23083

RT_CONSTANT() is only valid when op1 is a literal, so a CV or TMP operand
turned a frame offset into a pointer inside the opline array. Read the
operand from the call frame instead unless op1_type is IS_CONST.

Close GH-23095

Changed paths:
  A  Zend/tests/gh23083.phpt
  M  NEWS
  M  Zend/zend_exceptions.c


Diff:

diff --git a/NEWS b/NEWS
index b6d2b227ce2f..7bad8e58adcb 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,8 @@ PHP                                                                        NEWS
 - Core:
   . Changed run-tests.php to run test subprocesses without a shell where
     possible. (NickSdot)
+  . Fixed GH-23083 (SEGV build_trace_args in zend_exceptions.c with
+    -d error_include_args=On). (David Carlier)
 
 - Curl:
   . Improved cURL option validation errors to include the option name.
diff --git a/Zend/tests/gh23083.phpt b/Zend/tests/gh23083.phpt
new file mode 100644
index 000000000000..a731a987967d
--- /dev/null
+++ b/Zend/tests/gh23083.phpt
@@ -0,0 +1,32 @@
+--TEST--
+GH-23083 (SEGV in build_trace_args() with error_include_args=On and a non-literal include argument)
+--INI--
+error_include_args=On
+--FILE--
+<?php
+
+$file = 'no_such_file';
+
+/* CV operand */
+include $file;
+
+/* TMP operand */
+include $file . '_2';
+
+/* CV operand holding a reference */
+$ref = &$file;
+include $ref;
+
+?>
+--EXPECTF--
+Warning: include('no_such_file'): Failed to open stream: No such file or directory in %s on line %d
+
+Warning: include('no_such_file'): Failed opening 'no_such_file' for inclusion (include_path='%s') in %s on line %d
+
+Warning: include('no_such_file_2'): Failed to open stream: No such file or directory in %s on line %d
+
+Warning: include('no_such_file_2'): Failed opening 'no_such_file_2' for inclusion (include_path='%s') in %s on line %d
+
+Warning: include('no_such_file'): Failed to open stream: No such file or directory in %s on line %d
+
+Warning: include('no_such_file'): Failed opening 'no_such_file' for inclusion (include_path='%s') in %s on line %d
diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c
index ca91ec0ce12b..1b8297881d60 100644
--- a/Zend/zend_exceptions.c
+++ b/Zend/zend_exceptions.c
@@ -637,7 +637,17 @@ ZEND_API zend_string *zend_trace_current_function_args_string(void) {
 	if (execute_data && execute_data->func
 			&& ZEND_USER_CODE(execute_data->func->common.type)
 			&& (execute_data->opline->opcode == ZEND_INCLUDE_OR_EVAL)) {
-		zval *inc_filename = RT_CONSTANT(execute_data->opline, execute_data->opline->op1);
+		zval *inc_filename;
+
+		switch (execute_data->opline->op1_type) {
+			/* op1 may be CONST, TMP or CV; RT_CONSTANT() is only valid for the former. */
+			case IS_CONST:
+				inc_filename = RT_CONSTANT(execute_data->opline, execute_data->opline->op1);
+				break;
+			default:
+				inc_filename = EX_VAR(execute_data->opline->op1.var);
+		}
+
 		smart_str str = {0};
 		build_trace_args(inc_filename, &str);
 		return smart_str_extract(&str);
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.