diff --git a/ext/dom/documenttype.c b/ext/dom/documenttype.c index 266c895effb27..958559801a53d 100644 --- a/ext/dom/documenttype.c +++ b/ext/dom/documenttype.c @@ -53,7 +53,7 @@ zend_result dom_documenttype_entities_read(dom_object *obj, zval *retval) { DOM_PROP_NODE(xmlDtdPtr, dtdptr, obj); - object_init_ex(retval, dom_get_dtd_namednodemap_ce(php_dom_follow_spec_intern(obj))); + object_init_ex(retval, dom_get_dtd_namednodemap_ce(instanceof_function(obj->std.ce, dom_modern_documenttype_class_entry))); xmlHashTable *entityht = (xmlHashTable *) dtdptr->entities; @@ -74,7 +74,7 @@ zend_result dom_documenttype_notations_read(dom_object *obj, zval *retval) { DOM_PROP_NODE(xmlDtdPtr, dtdptr, obj); - object_init_ex(retval, dom_get_dtd_namednodemap_ce(php_dom_follow_spec_intern(obj))); + object_init_ex(retval, dom_get_dtd_namednodemap_ce(instanceof_function(obj->std.ce, dom_modern_documenttype_class_entry))); xmlHashTable *notationht = (xmlHashTable *) dtdptr->notations; diff --git a/ext/dom/dom_properties.h b/ext/dom/dom_properties.h index 43ff3417ebbd1..53113b04005a0 100644 --- a/ext/dom/dom_properties.h +++ b/ext/dom/dom_properties.h @@ -104,6 +104,7 @@ zend_result dom_entity_version_read(dom_object *obj, zval *retval); zend_result dom_entity_reference_child_read(dom_object *obj, zval *retval); zend_result dom_entity_reference_text_content_read(dom_object *obj, zval *retval); zend_result dom_entity_reference_child_nodes_read(dom_object *obj, zval *retval); +zend_result dom_modern_entity_reference_child_nodes_read(dom_object *obj, zval *retval); /* namednodemap properties */ zend_result dom_namednodemap_length_read(dom_object *obj, zval *retval); @@ -122,6 +123,7 @@ zend_result dom_node_node_type_read(dom_object *obj, zval *retval); zend_result dom_node_parent_node_read(dom_object *obj, zval *retval); zend_result dom_node_parent_element_read(dom_object *obj, zval *retval); zend_result dom_node_child_nodes_read(dom_object *obj, zval *retval); +zend_result dom_modern_node_child_nodes_read(dom_object *obj, zval *retval); zend_result dom_node_first_child_read(dom_object *obj, zval *retval); zend_result dom_node_last_child_read(dom_object *obj, zval *retval); zend_result dom_node_previous_sibling_read(dom_object *obj, zval *retval); diff --git a/ext/dom/entityreference.c b/ext/dom/entityreference.c index bea49d85d0f62..215df208f5305 100644 --- a/ext/dom/entityreference.c +++ b/ext/dom/entityreference.c @@ -106,4 +106,12 @@ zend_result dom_entity_reference_child_nodes_read(dom_object *obj, zval *retval) return dom_node_child_nodes_read(obj, retval); } +zend_result dom_modern_entity_reference_child_nodes_read(dom_object *obj, zval *retval) +{ + DOM_PROP_NODE(xmlNodePtr, nodep, obj); + + dom_entity_reference_fetch_and_sync_declaration(nodep); + return dom_modern_node_child_nodes_read(obj, retval); +} + #endif diff --git a/ext/dom/node.c b/ext/dom/node.c index 834c09f8e18b4..19b6c2eeae3b9 100644 --- a/ext/dom/node.c +++ b/ext/dom/node.c @@ -294,7 +294,18 @@ zend_result dom_node_child_nodes_read(dom_object *obj, zval *retval) { DOM_PROP_NODE(xmlNodePtr, nodep, obj); - object_init_ex(retval, dom_get_nodelist_ce(php_dom_follow_spec_intern(obj))); + object_init_ex(retval, dom_get_nodelist_ce(false)); + dom_object *intern = Z_DOMOBJ_P(retval); + php_dom_create_obj_map(obj, intern, NULL, NULL, NULL, &php_dom_obj_map_child_nodes); + + return SUCCESS; +} + +zend_result dom_modern_node_child_nodes_read(dom_object *obj, zval *retval) +{ + DOM_PROP_NODE(xmlNodePtr, nodep, obj); + + object_init_ex(retval, dom_get_nodelist_ce(true)); dom_object *intern = Z_DOMOBJ_P(retval); php_dom_create_obj_map(obj, intern, NULL, NULL, NULL, &php_dom_obj_map_child_nodes); diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index 2666cfdae7200..33a22e47c7800 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -904,7 +904,7 @@ PHP_MINIT_FUNCTION(dom) DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "ownerDocument", dom_node_owner_document_read, NULL); DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "parentNode", dom_node_parent_node_read, NULL); DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "parentElement", dom_node_parent_element_read, NULL); - DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "childNodes", dom_node_child_nodes_read, NULL); + DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "childNodes", dom_modern_node_child_nodes_read, NULL); DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "firstChild", dom_node_first_child_read, NULL); DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "lastChild", dom_node_last_child_read, NULL); DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "previousSibling", dom_node_previous_sibling_read, NULL); @@ -1305,7 +1305,7 @@ PHP_MINIT_FUNCTION(dom) DOM_OVERWRITE_PROP_HANDLER(&dom_modern_entity_reference_prop_handlers, "firstChild", dom_entity_reference_child_read, NULL); DOM_OVERWRITE_PROP_HANDLER(&dom_modern_entity_reference_prop_handlers, "lastChild", dom_entity_reference_child_read, NULL); DOM_OVERWRITE_PROP_HANDLER(&dom_modern_entity_reference_prop_handlers, "textContent", dom_entity_reference_text_content_read, NULL); - DOM_OVERWRITE_PROP_HANDLER(&dom_modern_entity_reference_prop_handlers, "childNodes", dom_entity_reference_child_nodes_read, NULL); + DOM_OVERWRITE_PROP_HANDLER(&dom_modern_entity_reference_prop_handlers, "childNodes", dom_modern_entity_reference_child_nodes_read, NULL); zend_hash_add_new_ptr(&classes, dom_modern_entityreference_class_entry->name, &dom_modern_entity_reference_prop_handlers); dom_processinginstruction_class_entry = register_class_DOMProcessingInstruction(dom_node_class_entry); diff --git a/ext/dom/tests/modern/common/gh21097.phpt b/ext/dom/tests/modern/common/gh21097.phpt new file mode 100644 index 0000000000000..db6abd12fcf7e --- /dev/null +++ b/ext/dom/tests/modern/common/gh21097.phpt @@ -0,0 +1,49 @@ +--TEST-- +GH-21097 (Accessing Dom\Node properties can can throw TypeError(s)) +--EXTENSIONS-- +dom +--CREDITS-- +mbeccati +--FILE-- +createDocumentType('html', 'publicId', 'systemId'); + +$r = new \ReflectionClass($node); +foreach ($r->getProperties(\ReflectionProperty::IS_PUBLIC) as $p) { + echo $p->getName(), ": "; + var_dump($node->{$p->getName()}); +} + +?> +--EXPECT-- +nodeType: int(10) +nodeName: string(4) "html" +baseURI: string(11) "about:blank" +isConnected: bool(false) +ownerDocument: NULL +parentNode: NULL +parentElement: NULL +childNodes: object(Dom\NodeList)#24 (1) { + ["length"]=> + int(0) +} +firstChild: NULL +lastChild: NULL +previousSibling: NULL +nextSibling: NULL +nodeValue: NULL +textContent: string(0) "" +name: string(4) "html" +entities: object(Dom\DtdNamedNodeMap)#24 (1) { + ["length"]=> + int(0) +} +notations: object(Dom\DtdNamedNodeMap)#24 (1) { + ["length"]=> + int(0) +} +publicId: string(8) "publicId" +systemId: string(8) "systemId" +internalSubset: NULL diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index 1bf74dd77eeab..77a06370cc738 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -1198,6 +1198,11 @@ PHP_FUNCTION(mysqli_options) MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED); expected_type = mysqli_options_get_option_zval_type(mysql_option); + if (expected_type == IS_NULL) { + zend_argument_value_error(ERROR_ARG_POS(2), "must be MYSQLI_INIT_COMMAND, MYSQLI_SET_CHARSET_NAME, MYSQLI_SERVER_PUBLIC_KEY, or one of the MYSQLI_OPT_* constants"); + RETURN_THROWS(); + } + if (expected_type != Z_TYPE_P(mysql_value)) { switch (expected_type) { case IS_STRING: diff --git a/ext/mysqli/tests/gh20968.phpt b/ext/mysqli/tests/gh20968.phpt new file mode 100644 index 0000000000000..e78e1378091ee --- /dev/null +++ b/ext/mysqli/tests/gh20968.phpt @@ -0,0 +1,26 @@ +--TEST-- +GH-20968 mysqli_options() with invalid option should triggers ValueError +--EXTENSIONS-- +mysqli +--CONFLICTS-- +mysqli +--SKIPIF-- + +--FILE-- +options(10, 'invalid_option'); + var_dump($value); +} catch (ValueError $exception) { + echo $exception->getMessage() . "\n"; +} + +?> +--EXPECTF-- +mysqli::options(): Argument #%d ($option) must be MYSQLI_INIT_COMMAND, MYSQLI_SET_CHARSET_NAME, MYSQLI_SERVER_PUBLIC_KEY, or one of the MYSQLI_OPT_* constants diff --git a/ext/mysqli/tests/mysqli_options.phpt b/ext/mysqli/tests/mysqli_options.phpt index 64e42dc752b1a..44647f80d1946 100644 --- a/ext/mysqli/tests/mysqli_options.phpt +++ b/ext/mysqli/tests/mysqli_options.phpt @@ -60,7 +60,13 @@ var_dump("MYSQLI_OPT_LOCAL_INFILE", mysqli_options($link, MYSQLI_OPT_LOCAL_INFIL var_dump("MYSQLI_INIT_COMMAND", mysqli_options($link, MYSQLI_INIT_COMMAND, 'SET AUTOCOMMIT=0')); /* mysqli_real_connect() */ -var_dump("MYSQLI_CLIENT_SSL", mysqli_options($link, MYSQLI_CLIENT_SSL, 'not a mysqli_option')); +var_dump("MYSQLI_CLIENT_SSL"); + +try { + var_dump(mysqli_options($link, MYSQLI_CLIENT_SSL, 'not a mysqli_option')); +} catch (ValueError $exception) { + echo $exception->getMessage() . "\n"; +} mysqli_close($link); @@ -81,9 +87,6 @@ try { echo $e->getMessage() . "\n"; } -// invalid options do not generate errors -mysqli_options($link, -1, "Invalid option"); - print "done!"; ?> --EXPECTF-- @@ -110,7 +113,7 @@ bool(true) %s(19) "MYSQLI_INIT_COMMAND" bool(true) %s(17) "MYSQLI_CLIENT_SSL" -bool(false) +mysqli_options(): Argument #%d ($option) must be MYSQLI_INIT_COMMAND, MYSQLI_SET_CHARSET_NAME, MYSQLI_SERVER_PUBLIC_KEY, or one of the MYSQLI_OPT_* constants Link closed mysqli object is already closed Unknown character set diff --git a/ext/mysqli/tests/mysqli_set_opt.phpt b/ext/mysqli/tests/mysqli_set_opt.phpt index 218e9f5177869..4518201e4d1f8 100644 --- a/ext/mysqli/tests/mysqli_set_opt.phpt +++ b/ext/mysqli/tests/mysqli_set_opt.phpt @@ -24,7 +24,12 @@ require_once 'skipifconnectfailure.inc'; var_dump(mysqli_set_opt($link, MYSQLI_OPT_CONNECT_TIMEOUT, 10)); var_dump(mysqli_set_opt($link, MYSQLI_OPT_LOCAL_INFILE, 1)); var_dump(mysqli_set_opt($link, MYSQLI_INIT_COMMAND, 'SET AUTOCOMMIT=0')); - var_dump(mysqli_set_opt($link, MYSQLI_CLIENT_SSL, 'not an mysqli_option')); + + try { + var_dump(mysqli_set_opt($link, MYSQLI_CLIENT_SSL, 'not an mysqli_option')); + } catch (ValueError $exception) { + echo $exception->getMessage() . "\n"; + } mysqli_close($link); @@ -48,6 +53,6 @@ bool(true) bool(true) bool(true) bool(true) -bool(false) +mysqli_set_opt(): Argument #2 ($option) must be MYSQLI_INIT_COMMAND, MYSQLI_SET_CHARSET_NAME, MYSQLI_SERVER_PUBLIC_KEY, or one of the MYSQLI_OPT_* constants mysqli object is already closed done!