-
Notifications
You must be signed in to change notification settings - Fork 8.1k
GH-22905: avoid truncation on null bytes in reflection exceptions #22922
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| --TEST-- | ||
| GH-22905: null bytes in ReflectionClassConstant::__construct() error messages (class name) | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| new ReflectionClassConstant("foo\0bar", ""); | ||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: Uncaught ReflectionException: Class "foo%0bar" does not exist in %s:%d | ||
| Stack trace: | ||
| #0 %s(%d): ReflectionClassConstant->__construct('foo\x00bar', '') | ||
| #1 {main} | ||
| thrown in %s on line %d |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| --TEST-- | ||
| GH-22905: null bytes in ReflectionClassConstant::__construct() error messages (constant name) | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| class Demo {} | ||
| new ReflectionClassConstant(Demo::class, "foo\0bar"); | ||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: Uncaught ReflectionException: Constant Demo::foo%0bar does not exist in %s:%d | ||
| Stack trace: | ||
| #0 %s(%d): ReflectionClassConstant->__construct('Demo', 'foo\x00bar') | ||
| #1 {main} | ||
| thrown in %s on line %d |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| --TEST-- | ||
| GH-22905: null bytes in ReflectionClass::__construct() error messages | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| new ReflectionClass("foo\0bar"); | ||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: Uncaught ReflectionException: Class "foo%0bar" does not exist in %s:%d | ||
| Stack trace: | ||
| #0 %s(%d): ReflectionClass->__construct('foo\x00bar') | ||
| #1 {main} | ||
| thrown in %s on line %d | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| --TEST-- | ||
| GH-22905: null bytes in ReflectionClass::getMethod() error messages | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| class Demo {} | ||
| $r = new ReflectionClass(Demo::class); | ||
| $r->getMethod("foo\0bar"); | ||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: Uncaught ReflectionException: Method Demo::foo%0bar() does not exist in %s:%d | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it possible to have a method with a null byte? If not using path ZPP might be better. |
||
| Stack trace: | ||
| #0 %s(%d): ReflectionClass->getMethod('foo\x00bar') | ||
| #1 {main} | ||
| thrown in %s on line %d | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| --TEST-- | ||
| GH-22905: null bytes in ReflectionClass::getProperty() error messages | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| class Demo {} | ||
| $r = new ReflectionClass(Demo::class); | ||
| $r->getProperty("foo\0bar"); | ||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: Uncaught ReflectionException: Property Demo::$foo%0bar does not exist in %s:%d | ||
| Stack trace: | ||
| #0 %s(%d): ReflectionClass->getProperty('foo\x00bar') | ||
| #1 {main} | ||
| thrown in %s on line %d |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| --TEST-- | ||
| GH-22905: null bytes in ReflectionClass::getProperty() (fully qualified, base class) error messages | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| class Base {} | ||
| class Demo extends Base {} | ||
| $r = new ReflectionClass(Demo::class); | ||
| $r->getProperty("Base::foo\0bar"); | ||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: Uncaught ReflectionException: Property Base::$foo%0bar does not exist in %s:%d | ||
| Stack trace: | ||
| #0 %s(%d): ReflectionClass->getProperty('Base::foo\x00bar') | ||
| #1 {main} | ||
| thrown in %s on line %d |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| --TEST-- | ||
| GH-22905: null bytes in ReflectionClass::getProperty() (fully qualified, non-base class) error messages | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| class Base {} | ||
| class Demo {} | ||
| $r = new ReflectionClass(Demo::class); | ||
| $r->getProperty("Base::foo\0bar"); | ||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: Uncaught ReflectionException: Fully qualified property name Base::$foo%0bar does not specify a base class of Demo in %s:%d | ||
| Stack trace: | ||
| #0 %s(%d): ReflectionClass->getProperty('Base::foo\x00bar') | ||
| #1 {main} | ||
| thrown in %s on line %d |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| --TEST-- | ||
| GH-22905: null bytes in ReflectionClass::getStaticPropertyValue() error messages | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| class Demo {} | ||
| $r = new ReflectionClass(Demo::class); | ||
| $r->getStaticPropertyValue("foo\0bar"); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure it's possible to have a static property to have a NUL byte? |
||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: Uncaught ReflectionException: Property Demo::$foo%0bar does not exist in %s:%d | ||
| Stack trace: | ||
| #0 %s(%d): ReflectionClass->getStaticPropertyValue('foo\x00bar') | ||
| #1 {main} | ||
| thrown in %s on line %d | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| --TEST-- | ||
| GH-22905: null bytes in ReflectionClass::implementsInterface() error messages | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| class Demo {} | ||
| $r = new ReflectionClass(Demo::class); | ||
| $r->implementsInterface("foo\0bar"); | ||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: Uncaught ReflectionException: Interface "foo%0bar" does not exist in %s:%d | ||
| Stack trace: | ||
| #0 %s(%d): ReflectionClass->implementsInterface('foo\x00bar') | ||
| #1 {main} | ||
| thrown in %s on line %d |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| --TEST-- | ||
| GH-22905: null bytes in ReflectionClass::isSubclassOf() error messages | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| class Demo {} | ||
| $r = new ReflectionClass(Demo::class); | ||
| $r->isSubclassOf("foo\0bar"); | ||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: Uncaught ReflectionException: Class "foo%0bar" does not exist in %s:%d | ||
| Stack trace: | ||
| #0 %s(%d): ReflectionClass->isSubclassOf('foo\x00bar') | ||
| #1 {main} | ||
| thrown in %s on line %d |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| --TEST-- | ||
| GH-22905: null bytes in ReflectionClass::setStaticPropertyValue() error messages | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| class Demo {} | ||
| $r = new ReflectionClass(Demo::class); | ||
| $r->setStaticPropertyValue("foo\0bar", 123); | ||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: Uncaught ReflectionException: Class Demo does not have a property named foo%0bar in %s:%d | ||
| Stack trace: | ||
| #0 %s(%d): ReflectionClass->setStaticPropertyValue('foo\x00bar', 123) | ||
| #1 {main} | ||
| thrown in %s on line %d |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| --TEST-- | ||
| GH-22905: null bytes in ReflectionConstant::__construct() error messages | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| new ReflectionConstant("foo\0bar"); | ||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: Uncaught ReflectionException: Constant "foo%0bar" does not exist in %s:%d | ||
| Stack trace: | ||
| #0 %s(%d): ReflectionConstant->__construct('foo\x00bar') | ||
| #1 {main} | ||
| thrown in %s on line %d |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| --TEST-- | ||
| GH-22905: null bytes in ReflectionEnum::getCase() error messages | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| enum Demo {} | ||
| $r = new ReflectionEnum(Demo::class); | ||
| $r->getCase("foo\0bar"); | ||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: Uncaught ReflectionException: Case Demo::foo%0bar does not exist in %s:%d | ||
| Stack trace: | ||
| #0 %s(%d): ReflectionEnum->getCase('foo\x00bar') | ||
| #1 {main} | ||
| thrown in %s on line %d |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| --TEST-- | ||
| GH-22905: null bytes in ReflectionExtension::__construct() error messages | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| new ReflectionExtension("foo\0bar"); | ||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: Uncaught ReflectionException: Extension "foo%0bar" does not exist in %s:%d | ||
| Stack trace: | ||
| #0 %s(%d): ReflectionExtension->__construct('foo\x00bar') | ||
| #1 {main} | ||
| thrown in %s on line %d |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| --TEST-- | ||
| GH-22905: null bytes in ReflectionFunction::__construct() error messages | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| new ReflectionFunction("foo\0bar"); | ||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: Uncaught ReflectionException: Function foo%0bar() does not exist in %s:%d | ||
| Stack trace: | ||
| #0 %s(%d): ReflectionFunction->__construct('foo\x00bar') | ||
| #1 {main} | ||
| thrown in %s on line %d |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| --TEST-- | ||
| GH-22905: null bytes in ReflectionMethod::__construct() error messages (class name) | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| new ReflectionMethod("foo\0bar", ""); | ||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: Uncaught ReflectionException: Class "foo%0bar" does not exist in %s:%d | ||
| Stack trace: | ||
| #0 %s(%d): ReflectionMethod->__construct('foo\x00bar', '') | ||
| #1 {main} | ||
| thrown in %s on line %d |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| --TEST-- | ||
| GH-22905: null bytes in ReflectionMethod::__construct() error messages (method name) | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| class Demo {} | ||
| new ReflectionMethod(Demo::class, "foo\0bar"); | ||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: Uncaught ReflectionException: Method Demo::foo%0bar() does not exist in %s:%d | ||
| Stack trace: | ||
| #0 %s(%d): ReflectionMethod->__construct('Demo', 'foo\x00bar') | ||
| #1 {main} | ||
| thrown in %s on line %d |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| --TEST-- | ||
| GH-22905: null bytes in ReflectionMethod::createFromMethodName() error messages (method name) | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| class Demo {} | ||
| ReflectionMethod::createFromMethodName("Demo::foo\0bar"); | ||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: Uncaught ReflectionException: Method Demo::foo%0bar() does not exist in %s:%d | ||
| Stack trace: | ||
| #0 %s(%d): ReflectionMethod::createFromMethodName('Demo::foo\x00bar') | ||
| #1 {main} | ||
| thrown in %s on line %d |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| --TEST-- | ||
| GH-22905: null bytes in ReflectionParameter::__construct() error messages (array class name) | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| new ReflectionParameter(["foo\0bar", ""], 0); | ||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: Uncaught ReflectionException: Class "foo%0bar" does not exist in %s:%d | ||
| Stack trace: | ||
| #0 %s(%d): ReflectionParameter->__construct(Array, 0) | ||
| #1 {main} | ||
| thrown in %s on line %d |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| --TEST-- | ||
| GH-22905: null bytes in ReflectionParameter::__construct() error messages (array method name) | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| class Demo {} | ||
| new ReflectionParameter([Demo::class, "foo\0bar"], 0); | ||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: Uncaught ReflectionException: Method Demo::foo%0bar() does not exist in %s:%d | ||
| Stack trace: | ||
| #0 %s(%d): ReflectionParameter->__construct(Array, 0) | ||
| #1 {main} | ||
| thrown in %s on line %d |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| --TEST-- | ||
| GH-22905: null bytes in ReflectionParameter::__construct() error messages (string function) | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| new ReflectionParameter("foo\0bar", 0); | ||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: Uncaught ReflectionException: Function foo%0bar() does not exist in %s:%d | ||
| Stack trace: | ||
| #0 %s(%d): ReflectionParameter->__construct('foo\x00bar', 0) | ||
| #1 {main} | ||
| thrown in %s on line %d |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to have a class name with null bytes? If not then just using the Path ZPP specifier would be better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anonymous classes have a null byte in their name
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah that is true, but isn't it assumed that the part after the null byte is truncate? I remember we added the Interface to the name as a way to distinguish between different anonymous classes.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure. Right now anonymous class names are a concatenation of the parent class/interface if any, followed by
@anonymous, a null byte, declaring file name, lineno, and a unique integer.::classreports the entire name including the null byte and what follows.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm maybe @nicolas-grekas can chime in as IIRC he asked for the parent class/interface to be added, so he might have more insight in what might be expected here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you mean get_debug_type vs the real class name?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the null byte is part of the class name and is needed for ReflectionClass::__construct(), https://3v4l.org/7LSSp#v
Edit: I didn't think of this before, this shows there is some truncation remaining in ReflectionClass::__toString() and probably a few other places