phpstan icon indicating copy to clipboard operation
phpstan copied to clipboard

ext/xml: set_*_handler() functions allows to set relative method names for callables

Open Girgias opened this issue 2 years ago • 4 comments
trafficstars

While doing some refactoring on ext/xml I discovered that the callable handler parameter has some rather strange semantics, in that it allows to set a method name to be called on the object set via xml_set_object()

Don't know if you want to fix this, but just raising awareness.

https://phpstan.org/r/cacb12c0-9730-41db-a969-f23ca0d27351

Related to:

  • https://github.com/php/php-src/pull/12340
  • https://github.com/php/doc-en/pull/2832

Girgias avatar Oct 03 '23 16:10 Girgias

I'd say that the parameter isn't of a callable type but generally a mixed type, or callable-array|string at best. That would get rid us of the error.

I'm checking the php-src stubs (extracted for PHPStan purposes) - the PHPDoc callable type should disappear: https://github.com/phpstan/php-8-stubs/blob/main/stubs/ext/xml/xml_set_character_data_handler.php

If we wanted then to check invalid inputs, we'd need a special rule with implemented logic for these scenarios.

ondrejmirtes avatar Oct 04 '23 12:10 ondrejmirtes

While working on the PR I'd consider the type to be "really" callable|string|null, as you can pass a normal callable string too. But maybe that's what callable-array|string is for?

Note the docs are currently saying that false is accepted to unset the handler which is true, but any value that cast to string which is an empty string has this behaviour.

The plan however is to make null (and empty strings for the time being) be the only way to disable a handler (so false would be coerced to an empty string in weak typing mode).

Girgias avatar Oct 04 '23 12:10 Girgias

Oh yeah, sure, there are other callables like an object with __invoke, so callable|string|null is correct.

ondrejmirtes avatar Oct 04 '23 12:10 ondrejmirtes

@Girgias After the latest push in 1.12.x, PHPStan now reports different result with your code snippet:

@@ @@
+PHP 8.4 (14 errors)
+==========
+
+ 5: Property XML_Parser::$dummy has no type specified.
+ 7: Method XML_Parser::parse() has no return type specified.
+ 7: Method XML_Parser::parse() has parameter $data with no type specified.
+13: Parameter #2 $start_handler of function xml_set_element_handler expects (callable(): mixed)|null, 'startHandler' given.
+13: Parameter #3 $end_handler of function xml_set_element_handler expects (callable(): mixed)|null, 'endHandler' given.
+20: Tip: Method XML_Parser::startHandler() always throws an exception, it should have return type "never".
+20: Method XML_Parser::startHandler() has no return type specified.
+20: Method XML_Parser::startHandler() has parameter $XmlParser with no type specified.
+20: Method XML_Parser::startHandler() has parameter $attr with no type specified.
+20: Method XML_Parser::startHandler() has parameter $tag with no type specified.
+26: Method XML_Parser::endHandler() has no return type specified.
+26: Method XML_Parser::endHandler() has parameter $XmlParser with no type specified.
+26: Method XML_Parser::endHandler() has parameter $tag with no type specified.
+31: Class XML_Parser referenced with incorrect case: Xml_Parser.
+
 PHP 8.0 – 8.3 (14 errors)
 ==========
 
Full report

PHP 8.4 (14 errors)

Line Error
5 Property XML_Parser::$dummy has no type specified.
7 Method XML_Parser::parse() has no return type specified.
7 Method XML_Parser::parse() has parameter $data with no type specified.
13 `Parameter #2 $start_handler of function xml_set_element_handler expects (callable(): mixed)
13 `Parameter #3 $end_handler of function xml_set_element_handler expects (callable(): mixed)
20 Tip: Method XML_Parser::startHandler() always throws an exception, it should have return type "never".
20 Method XML_Parser::startHandler() has no return type specified.
20 Method XML_Parser::startHandler() has parameter $XmlParser with no type specified.
20 Method XML_Parser::startHandler() has parameter $attr with no type specified.
20 Method XML_Parser::startHandler() has parameter $tag with no type specified.
26 Method XML_Parser::endHandler() has no return type specified.
26 Method XML_Parser::endHandler() has parameter $XmlParser with no type specified.
26 Method XML_Parser::endHandler() has parameter $tag with no type specified.
31 Class XML_Parser referenced with incorrect case: Xml_Parser.

PHP 8.0 – 8.3 (14 errors)

Line Error
5 Property XML_Parser::$dummy has no type specified.
7 Method XML_Parser::parse() has no return type specified.
7 Method XML_Parser::parse() has parameter $data with no type specified.
13 Parameter #2 $start_handler of function xml_set_element_handler expects callable(): mixed, 'startHandler' given.
13 Parameter #3 $end_handler of function xml_set_element_handler expects callable(): mixed, 'endHandler' given.
20 Tip: Method XML_Parser::startHandler() always throws an exception, it should have return type "never".
20 Method XML_Parser::startHandler() has no return type specified.
20 Method XML_Parser::startHandler() has parameter $XmlParser with no type specified.
20 Method XML_Parser::startHandler() has parameter $attr with no type specified.
20 Method XML_Parser::startHandler() has parameter $tag with no type specified.
26 Method XML_Parser::endHandler() has no return type specified.
26 Method XML_Parser::endHandler() has parameter $XmlParser with no type specified.
26 Method XML_Parser::endHandler() has parameter $tag with no type specified.
31 Class XML_Parser referenced with incorrect case: Xml_Parser.

PHP 7.2 – 7.4 (14 errors)

Line Error
5 Property XML_Parser::$dummy has no type specified.
7 Method XML_Parser::parse() has no return type specified.
7 Method XML_Parser::parse() has parameter $data with no type specified.
13 Parameter #2 $shdl of function xml_set_element_handler expects callable(): mixed, 'startHandler' given.
13 Parameter #3 $ehdl of function xml_set_element_handler expects callable(): mixed, 'endHandler' given.
20 Tip: Method XML_Parser::startHandler() always throws an exception, it should have return type "never".
20 Method XML_Parser::startHandler() has no return type specified.
20 Method XML_Parser::startHandler() has parameter $XmlParser with no type specified.
20 Method XML_Parser::startHandler() has parameter $attr with no type specified.
20 Method XML_Parser::startHandler() has parameter $tag with no type specified.
26 Method XML_Parser::endHandler() has no return type specified.
26 Method XML_Parser::endHandler() has parameter $XmlParser with no type specified.
26 Method XML_Parser::endHandler() has parameter $tag with no type specified.
31 Class XML_Parser referenced with incorrect case: Xml_Parser.

phpstan-bot avatar Aug 26 '24 21:08 phpstan-bot

@Girgias After the latest push in 2.1.x, PHPStan now reports different result with your code snippet:

@@ @@
  5: Property XML_Parser::$dummy has no type specified.
  7: Method XML_Parser::parse() has no return type specified.
  7: Method XML_Parser::parse() has parameter $data with no type specified.
-13: Parameter #2 $start_handler of function xml_set_element_handler expects callable(): mixed, 'startHandler' given.
-13: Parameter #3 $end_handler of function xml_set_element_handler expects callable(): mixed, 'endHandler' given.
+13: Parameter #2 $start_handler of function xml_set_element_handler expects (callable(): mixed)|null, 'startHandler' given.
+13: Parameter #3 $end_handler of function xml_set_element_handler expects (callable(): mixed)|null, 'endHandler' given.
 20: Tip: Method XML_Parser::startHandler() always throws an exception, it should have return type "never".
 20: Method XML_Parser::startHandler() has no return type specified.
 20: Method XML_Parser::startHandler() has parameter $XmlParser with no type specified.
Full report

PHP 8.0 – 8.3 (14 errors)

Line Error
5 Property XML_Parser::$dummy has no type specified.
7 Method XML_Parser::parse() has no return type specified.
7 Method XML_Parser::parse() has parameter $data with no type specified.
13 `Parameter #2 $start_handler of function xml_set_element_handler expects (callable(): mixed)
13 `Parameter #3 $end_handler of function xml_set_element_handler expects (callable(): mixed)
20 Tip: Method XML_Parser::startHandler() always throws an exception, it should have return type "never".
20 Method XML_Parser::startHandler() has no return type specified.
20 Method XML_Parser::startHandler() has parameter $XmlParser with no type specified.
20 Method XML_Parser::startHandler() has parameter $attr with no type specified.
20 Method XML_Parser::startHandler() has parameter $tag with no type specified.
26 Method XML_Parser::endHandler() has no return type specified.
26 Method XML_Parser::endHandler() has parameter $XmlParser with no type specified.
26 Method XML_Parser::endHandler() has parameter $tag with no type specified.
31 Class XML_Parser referenced with incorrect case: Xml_Parser.

PHP 7.2 – 7.4 (14 errors)

Line Error
5 Property XML_Parser::$dummy has no type specified.
7 Method XML_Parser::parse() has no return type specified.
7 Method XML_Parser::parse() has parameter $data with no type specified.
13 Parameter #2 $shdl of function xml_set_element_handler expects callable(): mixed, 'startHandler' given.
13 Parameter #3 $ehdl of function xml_set_element_handler expects callable(): mixed, 'endHandler' given.
20 Tip: Method XML_Parser::startHandler() always throws an exception, it should have return type "never".
20 Method XML_Parser::startHandler() has no return type specified.
20 Method XML_Parser::startHandler() has parameter $XmlParser with no type specified.
20 Method XML_Parser::startHandler() has parameter $attr with no type specified.
20 Method XML_Parser::startHandler() has parameter $tag with no type specified.
26 Method XML_Parser::endHandler() has no return type specified.
26 Method XML_Parser::endHandler() has parameter $XmlParser with no type specified.
26 Method XML_Parser::endHandler() has parameter $tag with no type specified.
31 Class XML_Parser referenced with incorrect case: Xml_Parser.

phpstan-bot avatar Sep 06 '25 07:09 phpstan-bot

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

github-actions[bot] avatar Oct 09 '25 01:10 github-actions[bot]