Commit 1db6c840500 for php.net
commit 1db6c840500192ecd26979a199068a23610cbc93
Author: Daniel Scherzer <daniel.e.scherzer@gmail.com>
Date: Fri Jul 10 12:52:05 2026 -0700
Add regression tests for `Reflection*::__toString()` with null bytes
So that when the outputs are fixed the changes can be confirmed in tests
diff --git a/ext/reflection/tests/gh22681/ReflectionClassConstant_doc_comment.phpt b/ext/reflection/tests/gh22681/ReflectionClassConstant_doc_comment.phpt
new file mode 100644
index 00000000000..49d646a4a19
--- /dev/null
+++ b/ext/reflection/tests/gh22681/ReflectionClassConstant_doc_comment.phpt
@@ -0,0 +1,44 @@
+--TEST--
+GH-22681: null bytes in doc comment truncate ReflectionClassConstant::__toString()
+--FILE--
+<?php
+
+eval(<<<END
+class Demo {
+ /** F\0oo */
+ public const DEMO = true;
+}
+END
+);
+
+$r = new ReflectionClassConstant(Demo::class, 'DEMO');
+echo $r;
+var_dump( $r->getDocComment() );
+
+echo new ReflectionClass(Demo::class);
+
+?>
+--EXPECTF--
+/** F
+Constant [ public bool DEMO ] { 1 }
+string(11) "/** F%0oo */"
+Class [ <user> class Demo ] {
+ @@ %s(%d) : eval()'d code %d-%d
+
+ - Constants [1] {
+ /** F
+ Constant [ public bool DEMO ] { 1 }
+ }
+
+ - Static properties [0] {
+ }
+
+ - Static methods [0] {
+ }
+
+ - Properties [0] {
+ }
+
+ - Methods [0] {
+ }
+}
diff --git a/ext/reflection/tests/gh22681/ReflectionClass_doc_comment.phpt b/ext/reflection/tests/gh22681/ReflectionClass_doc_comment.phpt
new file mode 100644
index 00000000000..c2da0400dcb
--- /dev/null
+++ b/ext/reflection/tests/gh22681/ReflectionClass_doc_comment.phpt
@@ -0,0 +1,37 @@
+--TEST--
+GH-22681: null bytes in doc comment truncate ReflectionClass::__toString()
+--FILE--
+<?php
+
+eval(<<<END
+/** F\0oo */
+class Demo {}
+END
+);
+
+$r = new ReflectionClass(Demo::class);
+echo $r;
+var_dump( $r->getDocComment() );
+
+?>
+--EXPECTF--
+/** F
+Class [ <user> class Demo ] {
+ @@ %s(%d) : eval()'d code %d-%d
+
+ - Constants [0] {
+ }
+
+ - Static properties [0] {
+ }
+
+ - Static methods [0] {
+ }
+
+ - Properties [0] {
+ }
+
+ - Methods [0] {
+ }
+}
+string(11) "/** F%0oo */"
diff --git a/ext/reflection/tests/gh22681/ReflectionConstant_name.phpt b/ext/reflection/tests/gh22681/ReflectionConstant_name.phpt
new file mode 100644
index 00000000000..a322596fa04
--- /dev/null
+++ b/ext/reflection/tests/gh22681/ReflectionConstant_name.phpt
@@ -0,0 +1,15 @@
+--TEST--
+GH-22681: null bytes in name truncate ReflectionConstant::__toString()
+--FILE--
+<?php
+
+define("F\0oo", true);
+
+$r = new ReflectionConstant("F\0oo");
+echo $r;
+var_dump( $r->getName() );
+
+?>
+--EXPECTF--
+Constant [ bool F ] { 1 }
+string(4) "F%0oo"
diff --git a/ext/reflection/tests/gh22681/ReflectionEnum_case_doc_comment.phpt b/ext/reflection/tests/gh22681/ReflectionEnum_case_doc_comment.phpt
new file mode 100644
index 00000000000..e76c0007c51
--- /dev/null
+++ b/ext/reflection/tests/gh22681/ReflectionEnum_case_doc_comment.phpt
@@ -0,0 +1,46 @@
+--TEST--
+GH-22681: null bytes in doc comment truncate ReflectionEnum::__toString()
+--FILE--
+<?php
+
+eval(<<<END
+enum Demo {
+ /** F\0oo */
+ case C;
+}
+END
+);
+
+$r = new ReflectionEnum(Demo::class);
+echo $r;
+var_dump( new ReflectionEnumUnitCase(Demo::class, 'C')->getDocComment() );
+?>
+--EXPECTF--
+Class [ <user> final class Demo implements UnitEnum ] {
+ @@ %s(%d) : eval()'d code %d-%d
+
+ - Constants [1] {
+ /** F
+ Constant [ public Demo C ] { Object }
+ }
+
+ - Static properties [0] {
+ }
+
+ - Static methods [1] {
+ Method [ <internal, prototype UnitEnum> static public method cases ] {
+
+ - Parameters [0] {
+ }
+ - Return [ array ]
+ }
+ }
+
+ - Properties [1] {
+ Property [ public protected(set) readonly string $name ]
+ }
+
+ - Methods [0] {
+ }
+}
+string(11) "/** F%0oo */"
diff --git a/ext/reflection/tests/gh22681/ReflectionExtension_ini_value.phpt b/ext/reflection/tests/gh22681/ReflectionExtension_ini_value.phpt
new file mode 100644
index 00000000000..42777ffd2fd
--- /dev/null
+++ b/ext/reflection/tests/gh22681/ReflectionExtension_ini_value.phpt
@@ -0,0 +1,23 @@
+--TEST--
+GH-22681: null bytes in INI values truncate ReflectionExtension::__toString()
+--FILE--
+<?php
+
+ini_set('arg_separator.output', "f\0oo");
+$r = new ReflectionExtension('core');
+$str = (string)$r;
+$index = strpos($str, 'Entry [ arg_separator.output');
+$str = substr($str, $index);
+$index = strpos($str, 'Entry', 1);
+$str = substr($str, 0, $index);
+echo $str . "\n";
+var_dump( $r->getINIEntries()['arg_separator.output'] );
+
+?>
+--EXPECTF--
+Entry [ arg_separator.output <ALL> ]
+ Current = 'f'
+ Default = '&'
+ }
+
+string(4) "f%0oo"
diff --git a/ext/reflection/tests/gh22681/ReflectionFunctionAbstract_doc_comment.phpt b/ext/reflection/tests/gh22681/ReflectionFunctionAbstract_doc_comment.phpt
new file mode 100644
index 00000000000..b7673de6c56
--- /dev/null
+++ b/ext/reflection/tests/gh22681/ReflectionFunctionAbstract_doc_comment.phpt
@@ -0,0 +1,36 @@
+--TEST--
+GH-22681: null bytes in doc comment truncate ReflectionFunctionAbstract::__toString()
+--FILE--
+<?php
+
+eval(<<<END
+/** F\0oo */
+function demo() {}
+
+class Demo {
+ /** B\0ar */
+ public function demo() {}
+}
+END
+);
+
+$r = new ReflectionFunction('demo');
+echo $r;
+var_dump( $r->getDocComment() );
+
+$r = new ReflectionMethod(Demo::class, 'demo');
+echo $r;
+var_dump( $r->getDocComment() );
+
+?>
+--EXPECTF--
+/** F
+Function [ <user> function demo ] {
+ @@ %s(%d) : eval()'d code %d - %d
+}
+string(11) "/** F%0oo */"
+/** B
+Method [ <user> public method demo ] {
+ @@ %s(%d) : eval()'d code %d - %d
+}
+string(11) "/** B%0ar */"
diff --git a/ext/reflection/tests/gh22681/ReflectionProperty_doc_comment.phpt b/ext/reflection/tests/gh22681/ReflectionProperty_doc_comment.phpt
new file mode 100644
index 00000000000..4f6f7c875e1
--- /dev/null
+++ b/ext/reflection/tests/gh22681/ReflectionProperty_doc_comment.phpt
@@ -0,0 +1,44 @@
+--TEST--
+GH-22681: null bytes in doc comment truncate ReflectionProperty::__toString()
+--FILE--
+<?php
+
+eval(<<<END
+class Demo {
+ /** F\0oo */
+ public \$prop;
+}
+END
+);
+
+$r = new ReflectionProperty(Demo::class, 'prop');
+echo $r;
+var_dump( $r->getDocComment() );
+
+echo new ReflectionClass(Demo::class);
+
+?>
+--EXPECTF--
+/** F
+Property [ public $prop = NULL ]
+string(11) "/** F%0oo */"
+Class [ <user> class Demo ] {
+ @@ %s(%d) : eval()'d code %d-%d
+
+ - Constants [0] {
+ }
+
+ - Static properties [0] {
+ }
+
+ - Static methods [0] {
+ }
+
+ - Properties [1] {
+ /** F
+ Property [ public $prop = NULL ]
+ }
+
+ - Methods [0] {
+ }
+}
diff --git a/ext/reflection/tests/gh22681/ReflectionProperty_dynamic_name.phpt b/ext/reflection/tests/gh22681/ReflectionProperty_dynamic_name.phpt
new file mode 100644
index 00000000000..921a738ea11
--- /dev/null
+++ b/ext/reflection/tests/gh22681/ReflectionProperty_dynamic_name.phpt
@@ -0,0 +1,37 @@
+--TEST--
+GH-22681: null bytes in name truncate ReflectionProperty::__toString()
+--FILE--
+<?php
+
+$obj = (object)["F\0oo" => true];
+$r = new ReflectionProperty($obj, "F\0oo");
+echo $r;
+var_dump( $r->getDocComment() );
+
+echo new ReflectionObject($obj);
+
+?>
+--EXPECT--
+Property [ <dynamic> public $F ]
+bool(false)
+Object of class [ <internal:Core> class stdClass ] {
+
+ - Constants [0] {
+ }
+
+ - Static properties [0] {
+ }
+
+ - Static methods [0] {
+ }
+
+ - Properties [0] {
+ }
+
+ - Dynamic properties [1] {
+ Property [ <dynamic> public $F ]
+ }
+
+ - Methods [0] {
+ }
+}