From 657167f17be00d4d833259d99ea4ee8c14bedf9c Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 22 Feb 2024 23:56:49 +0100 Subject: [PATCH] Destroy xpath callbacks at the time when the reconstruction happens --- ...Path_constructor_registered_functions.phpt | 53 +++++++++++++++++++ ext/dom/xpath.c | 2 + ext/dom/xpath_callbacks.c | 3 ++ 3 files changed, 58 insertions(+) create mode 100644 ext/dom/tests/DOMXPath_constructor_registered_functions.phpt diff --git a/ext/dom/tests/DOMXPath_constructor_registered_functions.phpt b/ext/dom/tests/DOMXPath_constructor_registered_functions.phpt new file mode 100644 index 00000000000..1fd498a5287 --- /dev/null +++ b/ext/dom/tests/DOMXPath_constructor_registered_functions.phpt @@ -0,0 +1,53 @@ +--TEST-- +DOMXPath: Calling __construct() again when functions were already registered +--EXTENSIONS-- +dom +--SKIPIF-- + +--FILE-- +loadXML(''); + +class Test { + public function __destruct() { + echo "destruct\n"; + } + + public function test() { + echo "test\n"; + } +} + +echo "=== First run ===\n"; + +$xpath = new DOMXPath($dom); +$xpath->registerNamespace('foo', 'urn:foo'); +$xpath->registerPhpFunctionNS('urn:foo', 'test', [new Test, 'test']); + +echo "=== Reconstruct ===\n"; + +$xpath->__construct($dom, true); + +echo "=== Second run ===\n"; + +$xpath->registerNamespace('foo', 'urn:foo'); +$xpath->query('//*[foo:test()]'); +$xpath->registerPhpFunctionNS('urn:foo', 'test', [new Test, 'test']); +$xpath->query('//*[foo:test()]'); + +?> +--EXPECTF-- +=== First run === +=== Reconstruct === +destruct +=== Second run === + +Warning: DOMXPath::query(): xmlXPathCompOpEval: function test not found in %s on line %d + +Warning: DOMXPath::query(): Unregistered function in %s on line %d +test +destruct diff --git a/ext/dom/xpath.c b/ext/dom/xpath.c index 9693a083e30..5a84fb5d868 100644 --- a/ext/dom/xpath.c +++ b/ext/dom/xpath.c @@ -137,6 +137,8 @@ PHP_METHOD(DOMXPath, __construct) if (oldctx != NULL) { php_libxml_decrement_doc_ref((php_libxml_node_object *) &intern->dom); xmlXPathFreeContext(oldctx); + php_dom_xpath_callbacks_dtor(&intern->xpath_callbacks); + php_dom_xpath_callbacks_ctor(&intern->xpath_callbacks); } xmlXPathRegisterFuncNS (ctx, (const xmlChar *) "functionString", diff --git a/ext/dom/xpath_callbacks.c b/ext/dom/xpath_callbacks.c index ced6cbc18a3..474972a5db2 100644 --- a/ext/dom/xpath_callbacks.c +++ b/ext/dom/xpath_callbacks.c @@ -46,6 +46,9 @@ PHP_DOM_EXPORT void php_dom_xpath_callback_ns_dtor(php_dom_xpath_callback_ns *ns PHP_DOM_EXPORT void php_dom_xpath_callbacks_ctor(php_dom_xpath_callbacks *registry) { + registry->php_ns = NULL; + registry->namespaces = NULL; + registry->node_list = NULL; } PHP_DOM_EXPORT void php_dom_xpath_callbacks_clean_node_list(php_dom_xpath_callbacks *registry)