Indirect Invocation Considered Harmful
source link: https://thephp.cc/articles/indirect-invocation-considered-harmful
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Indirect Invocation Considered Harmful
February 28, 2018
There is a bug in PHP that prevents scalar type declarations to be interpreted strictly when a function or method is invoked using the Reflection API.
Consider a class C
that has a method m
which expects a parameter $x
of type string:
Let us try to pass an integer instead of a string, which, when we enable strict interpretation of scalar type declarations, should yield a type error.
When we invoke that method directly, we get the error we expect:
<?php declare ( strict_types = 1 ) ; $o = new C ; $o -> m ( 1 ) ;Executing the code shown above will print the output shown below:
Fatal error: Uncaught TypeError: Argument 1 passed to C::m()
must be of the type string, integer given, called in ...
If we, however, invoke the method indirectly then PHP will not generate the expected type error.
<?php declare ( strict_types = 1 ) ; $object = new C ; $arguments = [ 1 ] ; $method = new ReflectionMethod ( $object , 'm' ) ; $method -> invokeArgs ( $object , $arguments ) ;This article is an excerpt from our eBook PHP 7 Explained.
Instead, executing the code shown above will print the output shown below:
string(1) "1"
While the discussion of that bug mentions that other forms of indirect invocation might also be affected, we were only able to reproduce the bug for the Reflection API. We tried callbacks with functions such as array_map()
, the call_user_func()
function, and the $object->$method()
syntax. For all these forms of indirect invocation a type error was raised, as is expected and correct.
In the example above, the Reflection API is used to invoke a method with arguments coming from an array. The same effect can be achieved using argument unpacking:
<?php declare ( strict_types = 1 ) ; $object = new C ; $arguments = [ 1 ] ; $object -> m ( ... $arguments ) ;Executing the code shown above will once again print:
Fatal error: Uncaught TypeError: Argument 1 passed to C::m()
must be of the type string, integer given, called in ...
We hope that developers do not use this bug in PHP to bypass type safety in code that they call – and, of course, that this bug will be fixed soon.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK