mirror of
https://github.com/php/php-src.git
synced 2026-10-29 10:22:06 +08:00
The SAX handler setters store their callback as a zend_fcall_info_cache on the parser and xml_set_handler() releases the previous one with zend_fcc_dtor(). None of the setters checked parser->isparsing, so calling xml_set_element_handler() (or any xml_set_*_handler()) from inside a running handler freed the fcc that was still executing. For a non-closure [$object, 'method'] handler whose object is only referenced by that fcc, the zend_fcc_dtor() releases the last reference and frees $this while its method is still on the stack, leading to a use-after-free. Guard xml_set_element_handler() and the XML_SET_HANDLER_PHP_FUNCTION setters with the existing isparsing flag and throw "Cannot change handlers while parsing", mirroring the checks already used by xml_parser_set_option() and xml_parse(). The parsed fcc is released on the error path like the other failure branches.