diff --git a/ext/dom/documenttype.c b/ext/dom/documenttype.c index 666dae56dc0f2..87d7a5cfb4307 100644 --- a/ext/dom/documenttype.c +++ b/ext/dom/documenttype.c @@ -52,7 +52,7 @@ zend_result dom_documenttype_entities_read(dom_object *obj, zval *retval) xmlHashTable *entityht = (xmlHashTable *) dtdptr->entities; dom_object *intern = Z_DOMOBJ_P(retval); - dom_namednode_iter(obj, XML_ENTITY_NODE, intern, entityht, NULL, 0, NULL, 0); + dom_namednode_iter(obj, XML_ENTITY_NODE, intern, entityht, NULL, NULL); return SUCCESS; } @@ -73,7 +73,7 @@ zend_result dom_documenttype_notations_read(dom_object *obj, zval *retval) xmlHashTable *notationht = (xmlHashTable *) dtdptr->notations; dom_object *intern = Z_DOMOBJ_P(retval); - dom_namednode_iter(obj, XML_NOTATION_NODE, intern, notationht, NULL, 0, NULL, 0); + dom_namednode_iter(obj, XML_NOTATION_NODE, intern, notationht, NULL, NULL); return SUCCESS; } diff --git a/ext/dom/element.c b/ext/dom/element.c index e96f4547d8f3f..65b94de9bad02 100644 --- a/ext/dom/element.c +++ b/ext/dom/element.c @@ -811,15 +811,14 @@ Modern spec URL: https://dom.spec.whatwg.org/#concept-getelementsbytagname */ static void dom_element_get_elements_by_tag_name(INTERNAL_FUNCTION_PARAMETERS, bool modern) { - size_t name_len; dom_object *intern, *namednode; - char *name; + zend_string *name; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &name, &name_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "P", &name) == FAILURE) { RETURN_THROWS(); } - if (name_len > INT_MAX) { + if (ZSTR_LEN(name) > INT_MAX) { zend_argument_value_error(1, "is too long"); RETURN_THROWS(); } @@ -832,7 +831,7 @@ static void dom_element_get_elements_by_tag_name(INTERNAL_FUNCTION_PARAMETERS, b php_dom_create_iterator(return_value, DOM_NODELIST, false); } namednode = Z_DOMOBJ_P(return_value); - dom_namednode_iter(intern, 0, namednode, NULL, name, name_len, NULL, 0); + dom_namednode_iter(intern, 0, namednode, NULL, name, NULL); } PHP_METHOD(DOMElement, getElementsByTagName) @@ -1239,20 +1238,23 @@ Since: DOM Level 2 */ static void dom_element_get_elements_by_tag_name_ns(INTERNAL_FUNCTION_PARAMETERS, bool modern) { - size_t uri_len, name_len; dom_object *intern, *namednode; - char *uri, *name; + zend_string *uri, *name; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "p!p", &uri, &uri_len, &name, &name_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "P!P", &uri, &name) == FAILURE) { RETURN_THROWS(); } - if (uri_len > INT_MAX) { + if (!uri) { + uri = ZSTR_EMPTY_ALLOC(); + } + + if (ZSTR_LEN(uri) > INT_MAX) { zend_argument_value_error(1, "is too long"); RETURN_THROWS(); } - if (name_len > INT_MAX) { + if (ZSTR_LEN(name) > INT_MAX) { zend_argument_value_error(2, "is too long"); RETURN_THROWS(); } @@ -1265,7 +1267,7 @@ static void dom_element_get_elements_by_tag_name_ns(INTERNAL_FUNCTION_PARAMETERS php_dom_create_iterator(return_value, DOM_NODELIST, false); } namednode = Z_DOMOBJ_P(return_value); - dom_namednode_iter(intern, 0, namednode, NULL, name, name_len, uri ? uri : "", uri_len); + dom_namednode_iter(intern, 0, namednode, NULL, name, uri); } PHP_METHOD(DOMElement, getElementsByTagNameNS) diff --git a/ext/dom/node.c b/ext/dom/node.c index fc8f0a58868c0..678b13610115a 100644 --- a/ext/dom/node.c +++ b/ext/dom/node.c @@ -283,7 +283,7 @@ zend_result dom_node_child_nodes_read(dom_object *obj, zval *retval) php_dom_create_iterator(retval, DOM_NODELIST, php_dom_follow_spec_intern(obj)); dom_object *intern = Z_DOMOBJ_P(retval); - dom_namednode_iter(obj, XML_ELEMENT_NODE, intern, NULL, NULL, 0, NULL, 0); + dom_namednode_iter(obj, XML_ELEMENT_NODE, intern, NULL, NULL, NULL); return SUCCESS; } @@ -417,7 +417,7 @@ zend_result dom_node_attributes_read(dom_object *obj, zval *retval) if (nodep->type == XML_ELEMENT_NODE) { php_dom_create_iterator(retval, DOM_NAMEDNODEMAP, php_dom_follow_spec_intern(obj)); dom_object *intern = Z_DOMOBJ_P(retval); - dom_namednode_iter(obj, XML_ATTRIBUTE_NODE, intern, NULL, NULL, 0, NULL, 0); + dom_namednode_iter(obj, XML_ATTRIBUTE_NODE, intern, NULL, NULL, NULL); } else { ZVAL_NULL(retval); } diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index f0fd4f5e8c744..c070b98cfb1bd 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -1452,7 +1452,7 @@ void dom_objects_free_storage(zend_object *object) } /* }}} */ -void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xmlHashTablePtr ht, const char *local, size_t local_len, const char *ns, size_t ns_len) /* {{{ */ +void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xmlHashTablePtr ht, zend_string *local, zend_string *ns) /* {{{ */ { dom_nnodemap_object *mapptr = (dom_nnodemap_object *) intern->ptr; @@ -1473,24 +1473,23 @@ void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xml const xmlChar* tmp; if (local) { - int len = (int) local_len; + int len = (int) ZSTR_LEN(local); if (doc != NULL && (tmp = xmlDictExists(doc->dict, (const xmlChar *)local, len)) != NULL) { mapptr->local = BAD_CAST tmp; } else { - mapptr->local = xmlCharStrndup(local, len); - mapptr->free_local = true; + mapptr->local = BAD_CAST ZSTR_VAL(zend_string_copy(local)); + mapptr->release_local = true; } - mapptr->local_lower = BAD_CAST estrdup(local); - zend_str_tolower((char *) mapptr->local_lower, len); + mapptr->local_lower = zend_string_tolower(local); } if (ns) { - int len = (int) ns_len; + int len = (int) ZSTR_LEN(ns); if (doc != NULL && (tmp = xmlDictExists(doc->dict, (const xmlChar *)ns, len)) != NULL) { mapptr->ns = BAD_CAST tmp; } else { - mapptr->ns = xmlCharStrndup(ns, len); - mapptr->free_ns = true; + mapptr->ns = BAD_CAST ZSTR_VAL(zend_string_copy(ns)); + mapptr->release_ns = true; } } } @@ -1561,6 +1560,11 @@ zend_object *dom_xpath_objects_new(zend_class_entry *class_type) #endif +/* The char pointer MUST refer to the char* of a zend_string struct */ +static void dom_zend_string_release_from_char_pointer(xmlChar *ptr) { + zend_string_release((zend_string*) (ptr - XtOffsetOf(zend_string, val))); +} + void dom_nnodemap_objects_free_storage(zend_object *object) /* {{{ */ { dom_object *intern = php_dom_obj_from_obj(object); @@ -1570,14 +1574,14 @@ void dom_nnodemap_objects_free_storage(zend_object *object) /* {{{ */ if (objmap->cached_obj && GC_DELREF(&objmap->cached_obj->std) == 0) { zend_objects_store_del(&objmap->cached_obj->std); } - if (objmap->free_local) { - xmlFree(objmap->local); + if (objmap->release_local) { + dom_zend_string_release_from_char_pointer(objmap->local); } - if (objmap->free_ns) { - xmlFree(objmap->ns); + if (objmap->release_ns) { + dom_zend_string_release_from_char_pointer(objmap->ns); } if (objmap->local_lower) { - efree(objmap->local_lower); + zend_string_release(objmap->local_lower); } if (!Z_ISUNDEF(objmap->baseobj_zv)) { zval_ptr_dtor(&objmap->baseobj_zv); @@ -1607,9 +1611,9 @@ zend_object *dom_nnodemap_objects_new(zend_class_entry *class_type) objmap->ht = NULL; objmap->local = NULL; objmap->local_lower = NULL; - objmap->free_local = false; + objmap->release_local = false; objmap->ns = NULL; - objmap->free_ns = false; + objmap->release_ns = false; objmap->cache_tag.modification_nr = 0; objmap->cached_length = -1; objmap->cached_obj = NULL; @@ -1865,7 +1869,7 @@ static bool dom_match_qualified_name_for_tag_name_equality(const xmlChar *local, return dom_match_qualified_name_according_to_spec(local_to_use, nodep); } -xmlNode *dom_get_elements_by_tag_name_ns_raw(xmlNodePtr basep, xmlNodePtr nodep, xmlChar *ns, xmlChar *local, xmlChar *local_lower, zend_long *cur, zend_long index) /* {{{ */ +xmlNode *dom_get_elements_by_tag_name_ns_raw(xmlNodePtr basep, xmlNodePtr nodep, const xmlChar *ns, const xmlChar *local, const zend_string *local_lower, zend_long *cur, zend_long index) /* {{{ */ { /* Can happen with detached document */ if (UNEXPECTED(nodep == NULL)) { @@ -1884,7 +1888,7 @@ xmlNode *dom_get_elements_by_tag_name_ns_raw(xmlNodePtr basep, xmlNodePtr nodep, while (*cur <= index) { if (nodep->type == XML_ELEMENT_NODE) { - if (local_match_any || dom_match_qualified_name_for_tag_name_equality(local, local_lower, nodep, match_qname)) { + if (local_match_any || dom_match_qualified_name_for_tag_name_equality(local, BAD_CAST ZSTR_VAL(local_lower), nodep, match_qname)) { if (ns_match_any || (ns[0] == '\0' && nodep->ns == NULL) || (nodep->ns != NULL && xmlStrEqual(nodep->ns->href, ns))) { if (*cur == index) { ret = nodep; diff --git a/ext/dom/php_dom.h b/ext/dom/php_dom.h index 8a2011d8ea432..37cefa0d480b7 100644 --- a/ext/dom/php_dom.h +++ b/ext/dom/php_dom.h @@ -83,14 +83,15 @@ typedef struct dom_nnodemap_object { int nodetype; int cached_length; xmlHashTable *ht; - xmlChar *local, *local_lower; + xmlChar *local; + zend_string *local_lower; xmlChar *ns; php_libxml_cache_tag cache_tag; dom_object *cached_obj; zend_long cached_obj_index; xmlDictPtr dict; - bool free_local : 1; - bool free_ns : 1; + bool release_local : 1; + bool release_ns : 1; } dom_nnodemap_object; typedef struct { @@ -144,14 +145,14 @@ void dom_reconcile_ns_list(xmlDocPtr doc, xmlNodePtr nodep, xmlNodePtr last); xmlNsPtr dom_get_nsdecl(xmlNode *node, xmlChar *localName); void php_dom_normalize_legacy(xmlNodePtr nodep); void php_dom_normalize_modern(xmlNodePtr nodep); -xmlNode *dom_get_elements_by_tag_name_ns_raw(xmlNodePtr basep, xmlNodePtr nodep, xmlChar *ns, xmlChar *local, xmlChar *local_lower, zend_long *cur, zend_long index); +xmlNode *dom_get_elements_by_tag_name_ns_raw(xmlNodePtr basep, xmlNodePtr nodep, const xmlChar *ns, const xmlChar *local, const zend_string *local_lower, zend_long *cur, zend_long index); void php_dom_create_implementation(zval *retval, bool modern); int dom_hierarchy(xmlNodePtr parent, xmlNodePtr child); bool dom_has_feature(zend_string *feature, zend_string *version); bool dom_node_is_read_only(const xmlNode *node); bool dom_node_children_valid(const xmlNode *node); void php_dom_create_iterator(zval *return_value, dom_iterator_type iterator_type, bool modern); -void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xmlHashTablePtr ht, const char *local, size_t local_len, const char *ns, size_t ns_len); +void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xmlHashTablePtr ht, zend_string *local, zend_string *ns); xmlNodePtr create_notation(const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID); xmlNode *php_dom_libxml_hash_iter(dom_nnodemap_object *objmap, int index); zend_object_iterator *php_dom_get_iterator(zend_class_entry *ce, zval *object, int by_ref);