mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Merge branch 'PHP-8.2'
* PHP-8.2: Fix DOMElement::append() and DOMElement::prepend() hierarchy checks Fix spec compliance error for DOMDocument::getElementsByTagNameNS Fix GH-11336: php still tries to unlock the shared memory ZendSem with opcache.file_cache_only=1 but it was never locked Fix GH-11338: SplFileInfo empty getBasename with more than one slash
This commit is contained in:
@@ -255,10 +255,33 @@ static void dom_fragment_assign_parent_node(xmlNodePtr parentNode, xmlNodePtr fr
|
||||
fragment->last = NULL;
|
||||
}
|
||||
|
||||
static zend_result dom_hierarchy_node_list(xmlNodePtr parentNode, zval *nodes, int nodesc)
|
||||
{
|
||||
for (int i = 0; i < nodesc; i++) {
|
||||
if (Z_TYPE(nodes[i]) == IS_OBJECT) {
|
||||
const zend_class_entry *ce = Z_OBJCE(nodes[i]);
|
||||
|
||||
if (instanceof_function(ce, dom_node_class_entry)) {
|
||||
if (dom_hierarchy(parentNode, dom_object_get_node(Z_DOMOBJ_P(nodes + i))) != SUCCESS) {
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void dom_parent_node_append(dom_object *context, zval *nodes, int nodesc)
|
||||
{
|
||||
xmlNode *parentNode = dom_object_get_node(context);
|
||||
xmlNodePtr newchild, prevsib;
|
||||
|
||||
if (UNEXPECTED(dom_hierarchy_node_list(parentNode, nodes, nodesc) != SUCCESS)) {
|
||||
php_dom_throw_error(HIERARCHY_REQUEST_ERR, dom_get_strict_error(context->document));
|
||||
return;
|
||||
}
|
||||
|
||||
xmlNode *fragment = dom_zvals_to_fragment(context->document, parentNode, nodes, nodesc);
|
||||
|
||||
if (fragment == NULL) {
|
||||
@@ -296,6 +319,11 @@ void dom_parent_node_prepend(dom_object *context, zval *nodes, int nodesc)
|
||||
return;
|
||||
}
|
||||
|
||||
if (UNEXPECTED(dom_hierarchy_node_list(parentNode, nodes, nodesc) != SUCCESS)) {
|
||||
php_dom_throw_error(HIERARCHY_REQUEST_ERR, dom_get_strict_error(context->document));
|
||||
return;
|
||||
}
|
||||
|
||||
xmlNodePtr newchild, nextsib;
|
||||
xmlNode *fragment = dom_zvals_to_fragment(context->document, parentNode, nodes, nodesc);
|
||||
|
||||
|
||||
@@ -1221,10 +1221,15 @@ xmlNode *dom_get_elements_by_tag_name_ns_raw(xmlNodePtr nodep, char *ns, char *l
|
||||
{
|
||||
xmlNodePtr ret = NULL;
|
||||
|
||||
/* Note: The spec says that ns == '' must be transformed to ns == NULL. In other words, they are equivalent.
|
||||
* PHP however does not do this and internally uses the empty string everywhere when the user provides ns == NULL.
|
||||
* This is because for PHP ns == NULL has another meaning: "match every namespace" instead of "match the empty namespace". */
|
||||
bool ns_match_any = ns == NULL || (ns[0] == '*' && ns[1] == '\0');
|
||||
|
||||
while (nodep != NULL && (*cur <= index || index == -1)) {
|
||||
if (nodep->type == XML_ELEMENT_NODE) {
|
||||
if (xmlStrEqual(nodep->name, (xmlChar *)local) || xmlStrEqual((xmlChar *)"*", (xmlChar *)local)) {
|
||||
if (ns == NULL || (!strcmp(ns, "") && nodep->ns == NULL) || (nodep->ns != NULL && (xmlStrEqual(nodep->ns->href, (xmlChar *)ns) || xmlStrEqual((xmlChar *)"*", (xmlChar *)ns)))) {
|
||||
if (ns_match_any || (!strcmp(ns, "") && nodep->ns == NULL) || (nodep->ns != NULL && xmlStrEqual(nodep->ns->href, (xmlChar *)ns))) {
|
||||
if (*cur == index) {
|
||||
ret = nodep;
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
--TEST--
|
||||
DOMDocument::getElementsByTagNameNS() match any namespace
|
||||
--EXTENSIONS--
|
||||
dom
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
/* Sample document taken from https://www.php.net/manual/en/domdocument.getelementsbytagname.php */
|
||||
$xml = <<<EOD
|
||||
<?xml version="1.0" ?>
|
||||
<chapter xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<title>Books of the other guy..</title>
|
||||
<para>
|
||||
<xi:include href="book.xml">
|
||||
<xi:fallback>
|
||||
<error>xinclude: book.xml not found</error>
|
||||
</xi:fallback>
|
||||
</xi:include>
|
||||
<include>
|
||||
This is another namespace
|
||||
</include>
|
||||
</para>
|
||||
</chapter>
|
||||
EOD;
|
||||
$dom = new DOMDocument;
|
||||
|
||||
// load the XML string defined above
|
||||
$dom->loadXML($xml);
|
||||
|
||||
function test($namespace, $local) {
|
||||
global $dom;
|
||||
$namespace_str = $namespace !== NULL ? "'$namespace'" : "null";
|
||||
echo "-- getElementsByTagNameNS($namespace_str, '$local') --\n";
|
||||
foreach ($dom->getElementsByTagNameNS($namespace, $local) as $element) {
|
||||
echo 'local name: \'', $element->localName, '\', prefix: \'', $element->prefix, "'\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Should *also* include objects even without a namespace
|
||||
test(null, '*');
|
||||
// Should *also* include objects even without a namespace
|
||||
test('*', '*');
|
||||
// Should *only* include objects without a namespace
|
||||
test('', '*');
|
||||
// Should *only* include objects with the specified namespace
|
||||
test('http://www.w3.org/2001/XInclude', '*');
|
||||
// Should not give any output
|
||||
test('', 'fallback');
|
||||
// Should not give any output, because the null namespace is the same as the empty namespace
|
||||
test(null, 'fallback');
|
||||
// Should only output the include from the empty namespace
|
||||
test(null, 'include');
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
-- getElementsByTagNameNS(null, '*') --
|
||||
local name: 'chapter', prefix: ''
|
||||
local name: 'title', prefix: ''
|
||||
local name: 'para', prefix: ''
|
||||
local name: 'error', prefix: ''
|
||||
local name: 'include', prefix: ''
|
||||
-- getElementsByTagNameNS('*', '*') --
|
||||
local name: 'chapter', prefix: ''
|
||||
local name: 'title', prefix: ''
|
||||
local name: 'para', prefix: ''
|
||||
local name: 'include', prefix: 'xi'
|
||||
local name: 'fallback', prefix: 'xi'
|
||||
local name: 'error', prefix: ''
|
||||
local name: 'include', prefix: ''
|
||||
-- getElementsByTagNameNS('', '*') --
|
||||
local name: 'chapter', prefix: ''
|
||||
local name: 'title', prefix: ''
|
||||
local name: 'para', prefix: ''
|
||||
local name: 'error', prefix: ''
|
||||
local name: 'include', prefix: ''
|
||||
-- getElementsByTagNameNS('http://www.w3.org/2001/XInclude', '*') --
|
||||
local name: 'include', prefix: 'xi'
|
||||
local name: 'fallback', prefix: 'xi'
|
||||
-- getElementsByTagNameNS('', 'fallback') --
|
||||
-- getElementsByTagNameNS(null, 'fallback') --
|
||||
-- getElementsByTagNameNS(null, 'include') --
|
||||
local name: 'include', prefix: ''
|
||||
89
ext/dom/tests/DOMElement_append_hierarchy_test.phpt
Normal file
89
ext/dom/tests/DOMElement_append_hierarchy_test.phpt
Normal file
@@ -0,0 +1,89 @@
|
||||
--TEST--
|
||||
DOMElement::append() with hierarchy changes and errors
|
||||
--EXTENSIONS--
|
||||
dom
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$dom_original = new DOMDocument;
|
||||
$dom_original->loadXML('<p><b>hello</b><b><i>world</i></b></p>');
|
||||
|
||||
echo "-- Append hello with world --\n";
|
||||
$dom = clone $dom_original;
|
||||
$b_hello = $dom->firstChild->firstChild;
|
||||
$b_world = $b_hello->nextSibling;
|
||||
$b_hello->append($b_world);
|
||||
var_dump($dom->saveHTML());
|
||||
|
||||
echo "-- Append hello with world's child --\n";
|
||||
$dom = clone $dom_original;
|
||||
$b_hello = $dom->firstChild->firstChild;
|
||||
$b_world = $b_hello->nextSibling;
|
||||
$b_hello->append($b_world->firstChild);
|
||||
var_dump($dom->saveHTML());
|
||||
|
||||
echo "-- Append world's child with hello --\n";
|
||||
$dom = clone $dom_original;
|
||||
$b_hello = $dom->firstChild->firstChild;
|
||||
$b_world = $b_hello->nextSibling;
|
||||
$b_world->firstChild->append($b_hello);
|
||||
var_dump($dom->saveHTML());
|
||||
|
||||
echo "-- Append hello with itself --\n";
|
||||
$dom = clone $dom_original;
|
||||
$b_hello = $dom->firstChild->firstChild;
|
||||
try {
|
||||
$b_hello->append($b_hello);
|
||||
} catch (\DOMException $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
var_dump($dom->saveHTML());
|
||||
|
||||
echo "-- Append world's i tag with the parent --\n";
|
||||
$dom = clone $dom_original;
|
||||
$b_hello = $dom->firstChild->firstChild;
|
||||
$b_world = $b_hello->nextSibling;
|
||||
try {
|
||||
$b_world->firstChild->append($b_world);
|
||||
} catch (\DOMException $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
var_dump($dom->saveHTML());
|
||||
|
||||
echo "-- Append from another document --\n";
|
||||
$dom = clone $dom_original;
|
||||
$dom2 = new DOMDocument;
|
||||
$dom2->loadXML('<p>other</p>');
|
||||
try {
|
||||
$dom->firstChild->firstChild->prepend($dom2->firstChild);
|
||||
} catch (\DOMException $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
var_dump($dom2->saveHTML());
|
||||
var_dump($dom->saveHTML());
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
-- Append hello with world --
|
||||
string(39) "<p><b>hello<b><i>world</i></b></b></p>
|
||||
"
|
||||
-- Append hello with world's child --
|
||||
string(39) "<p><b>hello<i>world</i></b><b></b></p>
|
||||
"
|
||||
-- Append world's child with hello --
|
||||
string(39) "<p><b><i>world<b>hello</b></i></b></p>
|
||||
"
|
||||
-- Append hello with itself --
|
||||
Hierarchy Request Error
|
||||
string(39) "<p><b>hello</b><b><i>world</i></b></p>
|
||||
"
|
||||
-- Append world's i tag with the parent --
|
||||
Hierarchy Request Error
|
||||
string(39) "<p><b>hello</b><b><i>world</i></b></p>
|
||||
"
|
||||
-- Append from another document --
|
||||
Wrong Document Error
|
||||
string(13) "<p>other</p>
|
||||
"
|
||||
string(39) "<p><b>hello</b><b><i>world</i></b></p>
|
||||
"
|
||||
89
ext/dom/tests/DOMElement_prepend_hierarchy_test.phpt
Normal file
89
ext/dom/tests/DOMElement_prepend_hierarchy_test.phpt
Normal file
@@ -0,0 +1,89 @@
|
||||
--TEST--
|
||||
DOMElement::prepend() with hierarchy changes and errors
|
||||
--EXTENSIONS--
|
||||
dom
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$dom_original = new DOMDocument;
|
||||
$dom_original->loadXML('<p><b>hello</b><b><i>world</i></b></p>');
|
||||
|
||||
echo "-- Prepend hello with world --\n";
|
||||
$dom = clone $dom_original;
|
||||
$b_hello = $dom->firstChild->firstChild;
|
||||
$b_world = $b_hello->nextSibling;
|
||||
$b_hello->prepend($b_world);
|
||||
var_dump($dom->saveHTML());
|
||||
|
||||
echo "-- Prepend hello with world's child --\n";
|
||||
$dom = clone $dom_original;
|
||||
$b_hello = $dom->firstChild->firstChild;
|
||||
$b_world = $b_hello->nextSibling;
|
||||
$b_hello->prepend($b_world->firstChild);
|
||||
var_dump($dom->saveHTML());
|
||||
|
||||
echo "-- Prepend world's child with hello --\n";
|
||||
$dom = clone $dom_original;
|
||||
$b_hello = $dom->firstChild->firstChild;
|
||||
$b_world = $b_hello->nextSibling;
|
||||
$b_world->firstChild->prepend($b_hello);
|
||||
var_dump($dom->saveHTML());
|
||||
|
||||
echo "-- Prepend hello with itself --\n";
|
||||
$dom = clone $dom_original;
|
||||
$b_hello = $dom->firstChild->firstChild;
|
||||
try {
|
||||
$b_hello->prepend($b_hello);
|
||||
} catch (\DOMException $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
var_dump($dom->saveHTML());
|
||||
|
||||
echo "-- Prepend world's i tag with the parent --\n";
|
||||
$dom = clone $dom_original;
|
||||
$b_hello = $dom->firstChild->firstChild;
|
||||
$b_world = $b_hello->nextSibling;
|
||||
try {
|
||||
$b_world->firstChild->prepend($b_world);
|
||||
} catch (\DOMException $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
var_dump($dom->saveHTML());
|
||||
|
||||
echo "-- Append from another document --\n";
|
||||
$dom = clone $dom_original;
|
||||
$dom2 = new DOMDocument;
|
||||
$dom2->loadXML('<p>other</p>');
|
||||
try {
|
||||
$dom->firstChild->firstChild->prepend($dom2->firstChild);
|
||||
} catch (\DOMException $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
var_dump($dom2->saveHTML());
|
||||
var_dump($dom->saveHTML());
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
-- Prepend hello with world --
|
||||
string(39) "<p><b><b><i>world</i></b>hello</b></p>
|
||||
"
|
||||
-- Prepend hello with world's child --
|
||||
string(39) "<p><b><i>world</i>hello</b><b></b></p>
|
||||
"
|
||||
-- Prepend world's child with hello --
|
||||
string(39) "<p><b><i><b>hello</b>world</i></b></p>
|
||||
"
|
||||
-- Prepend hello with itself --
|
||||
Hierarchy Request Error
|
||||
string(39) "<p><b>hello</b><b><i>world</i></b></p>
|
||||
"
|
||||
-- Prepend world's i tag with the parent --
|
||||
Hierarchy Request Error
|
||||
string(39) "<p><b>hello</b><b><i>world</i></b></p>
|
||||
"
|
||||
-- Append from another document --
|
||||
Wrong Document Error
|
||||
string(13) "<p>other</p>
|
||||
"
|
||||
string(39) "<p><b>hello</b><b><i>world</i></b></p>
|
||||
"
|
||||
@@ -390,6 +390,10 @@ static inline void accel_unlock_all(void)
|
||||
#ifdef ZEND_WIN32
|
||||
accel_deactivate_sub();
|
||||
#else
|
||||
if (lock_file == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct flock mem_usage_unlock_all;
|
||||
|
||||
mem_usage_unlock_all.l_type = F_UNLCK;
|
||||
|
||||
@@ -59,7 +59,7 @@ zend_smm_shared_globals *smm_shared_globals;
|
||||
#ifdef ZTS
|
||||
static MUTEX_T zts_lock;
|
||||
#endif
|
||||
int lock_file;
|
||||
int lock_file = -1;
|
||||
static char lockfile_name[MAXPATHLEN];
|
||||
#endif
|
||||
|
||||
|
||||
@@ -454,7 +454,9 @@ static void spl_filesystem_info_set_filename(spl_filesystem_object *intern, zend
|
||||
|
||||
path_len = ZSTR_LEN(path);
|
||||
if (path_len > 1 && IS_SLASH_AT(ZSTR_VAL(path), path_len-1)) {
|
||||
path_len--;
|
||||
do {
|
||||
path_len--;
|
||||
} while (path_len > 1 && IS_SLASH_AT(ZSTR_VAL(path), path_len - 1));
|
||||
intern->file_name = zend_string_init(ZSTR_VAL(path), path_len, 0);
|
||||
} else {
|
||||
intern->file_name = zend_string_copy(path);
|
||||
|
||||
47
ext/spl/tests/gh11338.phpt
Normal file
47
ext/spl/tests/gh11338.phpt
Normal file
@@ -0,0 +1,47 @@
|
||||
--TEST--
|
||||
GH-11338 (SplFileInfo empty getBasename with more than on slash)
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test($path) {
|
||||
echo "Testing: '$path'\n";
|
||||
$file = new \SplFileInfo($path);
|
||||
var_dump($file->getBasename());
|
||||
var_dump($file->getFilename());
|
||||
}
|
||||
|
||||
test('/dir/anotherdir/basedir//');
|
||||
test('/dir/anotherdir/basedir/');
|
||||
test('/dir/anotherdir/basedir');
|
||||
test('/dir/anotherdir//basedir');
|
||||
test('///');
|
||||
test('//');
|
||||
test('/');
|
||||
test('');
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Testing: '/dir/anotherdir/basedir//'
|
||||
string(7) "basedir"
|
||||
string(7) "basedir"
|
||||
Testing: '/dir/anotherdir/basedir/'
|
||||
string(7) "basedir"
|
||||
string(7) "basedir"
|
||||
Testing: '/dir/anotherdir/basedir'
|
||||
string(7) "basedir"
|
||||
string(7) "basedir"
|
||||
Testing: '/dir/anotherdir//basedir'
|
||||
string(7) "basedir"
|
||||
string(7) "basedir"
|
||||
Testing: '///'
|
||||
string(0) ""
|
||||
string(1) "/"
|
||||
Testing: '//'
|
||||
string(0) ""
|
||||
string(1) "/"
|
||||
Testing: '/'
|
||||
string(0) ""
|
||||
string(1) "/"
|
||||
Testing: ''
|
||||
string(0) ""
|
||||
string(0) ""
|
||||
Reference in New Issue
Block a user