Skip to content

Fix compatibility with libxml2 2.13.2 #14789

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions ext/dom/document.c
Original file line number Diff line number Diff line change
Expand Up @@ -1429,11 +1429,13 @@ xmlDocPtr dom_document_parser(zval *id, dom_load_mode mode, const char *source,
if (keep_blanks == 0 && ! (options & XML_PARSE_NOBLANKS)) {
options |= XML_PARSE_NOBLANKS;
}
if (recover) {
options |= XML_PARSE_RECOVER;
}

php_libxml_sanitize_parse_ctxt_options(ctxt);
xmlCtxtUseOptions(ctxt, options);

ctxt->recovery = recover;
if (recover) {
old_error_reporting = EG(error_reporting);
EG(error_reporting) = old_error_reporting | E_WARNING;
Expand All @@ -1443,7 +1445,7 @@ xmlDocPtr dom_document_parser(zval *id, dom_load_mode mode, const char *source,

if (ctxt->wellFormed || recover) {
ret = ctxt->myDoc;
if (ctxt->recovery) {
if (recover) {
EG(error_reporting) = old_error_reporting;
}
/* If loading from memory, set the base reference uri for the document */
Expand Down
2 changes: 1 addition & 1 deletion ext/dom/tests/DOMDocument_loadHTMLfile_error1.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ $result = $doc->loadHTMLFile(__DIR__ . "/ffff/test.html");
assert($result === false);
?>
--EXPECTF--
%r(PHP ){0,1}%rWarning: DOMDocument::loadHTMLFile(): I/O warning : failed to load external entity %s
%r(PHP ){0,1}%rWarning: DOMDocument::loadHTMLFile(): I/O %s
2 changes: 1 addition & 1 deletion ext/dom/tests/DOMDocument_loadXML_error2_gte2_12.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ domdocumentloadxml_test_method.inc
--EXPECTF--
Warning: DOMDocument::loadXML(): AttValue: " or ' expected in Entity, line: 4 in %s on line %d

Warning: DOMDocument::loadXML(): internal error: xmlParseStartTag: problem parsing attributes in Entity, line: 4 in %s on line %d
Warning: DOMDocument::loadXML():%sattributes%s

Warning: DOMDocument::loadXML(): Couldn't find end of Start Tag book line 4 in Entity, line: 4 in %s on line %d

Expand Down
2 changes: 1 addition & 1 deletion ext/dom/tests/DOMDocument_load_error2_gte2_12.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ domdocumentload_test_method.inc
--EXPECTF--
Warning: DOMDocument::load(): AttValue: " or ' expected in %s on line %d

Warning: DOMDocument::load(): internal error: xmlParseStartTag: problem parsing attributes in %s on line %d
Warning: DOMDocument::load():%sattributes%s

Warning: DOMDocument::load(): Couldn't find end of Start Tag book line 4 in %s on line %d

Expand Down
2 changes: 1 addition & 1 deletion ext/dom/tests/DOMDocument_relaxNGValidate_error2.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ $result = $doc->relaxNGValidate($rng);
var_dump($result);
?>
--EXPECTF--
Warning: DOMDocument::relaxNGValidate(): I/O warning : failed to load external entity "%s/foo.rng" in %s on line %d
Warning: DOMDocument::relaxNGValidate(): I/O %s : failed to load %s

Warning: DOMDocument::relaxNGValidate(): xmlRelaxNGParse: could not load %s/foo.rng in %s on line %d

Expand Down
4 changes: 4 additions & 0 deletions ext/dom/tests/DOMDocument_saveHTMLFile_basic.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ Knut Urdalen <[email protected]>
#PHPTestFest2009 Norway 2009-06-09 \o/
--EXTENSIONS--
dom
--SKIPIF--
<?php
if (LIBXML_VERSION >= 21300) die("skip see https://gitlab.gnome.org/GNOME/libxml2/-/issues/756");
?>
--FILE--
<?php
$filename = __DIR__."/DOMDocument_saveHTMLFile_basic.html";
Expand Down
4 changes: 4 additions & 0 deletions ext/dom/tests/DOMDocument_saveHTMLFile_formatOutput.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ Knut Urdalen <[email protected]>
#PHPTestFest2009 Norway 2009-06-09 \o/
--EXTENSIONS--
dom
--SKIPIF--
<?php
if (LIBXML_VERSION >= 21300) die("skip see https://gitlab.gnome.org/GNOME/libxml2/-/issues/756");
?>
--FILE--
<?php
$filename = __DIR__."/DOMDocument_saveHTMLFile_formatOutput.html";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
--TEST--
DOMDocument::saveHTMLFile() should format output on demand
--CREDITS--
Knut Urdalen <[email protected]>
#PHPTestFest2009 Norway 2009-06-09 \o/
Comment on lines +3 to +5
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused by the credits section here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copied over from the existing test, as almost everything is the same the credits still belong to this person. This test is a variant for libxml>=2.13.
Same for the other test.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK

--EXTENSIONS--
dom
--SKIPIF--
<?php
if (LIBXML_VERSION < 21300) die("skip see https://gitlab.gnome.org/GNOME/libxml2/-/issues/756");
?>
--FILE--
<?php
$filename = __DIR__."/DOMDocument_saveHTMLFile_formatOutput_gte_2_13.html";
$doc = new DOMDocument('1.0');
$doc->formatOutput = true;
$root = $doc->createElement('html');
$root = $doc->appendChild($root);
$head = $doc->createElement('head');
$head = $root->appendChild($head);
$title = $doc->createElement('title');
$title = $head->appendChild($title);
$text = $doc->createTextNode('This is the title');
$text = $title->appendChild($text);
$bytes = $doc->saveHTMLFile($filename);
var_dump($bytes);
echo file_get_contents($filename);
unlink($filename);
?>
--EXPECT--
int(59)
<html><head><title>This is the title</title></head></html>
31 changes: 31 additions & 0 deletions ext/dom/tests/DOMDocument_saveHTML_basic_gte_2_13.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
--TEST--
DOMDocument::saveHTMLFile() should dump the internal document into a file using HTML formatting
--CREDITS--
Knut Urdalen <[email protected]>
#PHPTestFest2009 Norway 2009-06-09 \o/
--EXTENSIONS--
Comment on lines +3 to +6
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto

dom
--SKIPIF--
<?php
if (LIBXML_VERSION < 21300) die("skip see https://gitlab.gnome.org/GNOME/libxml2/-/issues/756");
?>
--FILE--
<?php
$filename = __DIR__."/DOMDocument_saveHTMLFile_basic_gte_2_13.html";
$doc = new DOMDocument('1.0');
$root = $doc->createElement('html');
$root = $doc->appendChild($root);
$head = $doc->createElement('head');
$head = $root->appendChild($head);
$title = $doc->createElement('title');
$title = $head->appendChild($title);
$text = $doc->createTextNode('This is the title');
$text = $title->appendChild($text);
$bytes = $doc->saveHTMLFile($filename);
var_dump($bytes);
echo file_get_contents($filename);
unlink($filename);
?>
--EXPECT--
int(59)
<html><head><title>This is the title</title></head></html>
2 changes: 1 addition & 1 deletion ext/dom/tests/DOMDocument_schemaValidate_error5.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ var_dump($result);

?>
--EXPECTF--
Warning: DOMDocument::schemaValidate(): I/O warning : failed to load external entity "%snon-existent-file" in %s on line %d
Warning: DOMDocument::schemaValidate(): I/O %s : failed to load %s

Warning: DOMDocument::schemaValidate(): Failed to locate the main schema resource at '%snon-existent-file'. in %s on line %d

Expand Down
4 changes: 2 additions & 2 deletions ext/dom/tests/DOMEntityReference_predefined_free.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ dom
$ref = new DOMEntityReference("amp");
var_dump($ref);
?>
--EXPECT--
--EXPECTF--
object(DOMEntityReference)#1 (17) {
["nodeName"]=>
string(3) "amp"
Expand Down Expand Up @@ -42,5 +42,5 @@ object(DOMEntityReference)#1 (17) {
["baseURI"]=>
NULL
["textContent"]=>
string(0) ""
string(%d) "%S"
}
10 changes: 4 additions & 6 deletions ext/dom/tests/DOMXPath_constructor_registered_functions.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,17 @@ $xpath->__construct($dom, true);
echo "=== Second run ===\n";

$xpath->registerNamespace('foo', 'urn:foo');
$xpath->query('//*[foo:test()]');
// Note: since libxml2 commit aca16fb3d45e0b2c45364ffc1cea8eb4abaca87d this only outputs 1 warning. This seems intentional.
// Easiest workaround is silencing the warnings
@$xpath->query('//*[foo:test()]');
$xpath->registerPhpFunctionNS('urn:foo', 'test', [new Test, 'test']);
$xpath->query('//*[foo:test()]');

?>
--EXPECTF--
--EXPECT--
=== 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
14 changes: 4 additions & 10 deletions ext/dom/tests/dom_create_element.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -251,14 +251,10 @@ try {
print $e->getMessage() . "\n";
}

/* This isn't because the xml namespace isn't there and we can't create it */
print "29 DOMElement::__construct('xml:valid', '', 'http://www.w3.org/XML/1998/namespace')\n";
try {
$element = new DomElement('xml:valid', '', 'http://www.w3.org/XML/1998/namespace');
print "valid\n";
} catch (Exception $e) {
print $e->getMessage() . "\n";
}
/* There used to be a 29 here that tested DOMElement::__construct('xml:valid', '', 'http://www.w3.org/XML/1998/namespace').
* In libxml2 version 2.12 or prior this didn't work because the xml namespace isn't there and you can't create it without
* a document. Starting from libxml2 version 2.13 it does actually work because the XML namespace is statically defined.
* The behaviour from version 2.13 is actually the desired behaviour anyway. */


/* the qualifiedName or its prefix is "xmlns" and the namespaceURI is
Expand Down Expand Up @@ -378,8 +374,6 @@ Namespace Error
Namespace Error
28 DOMDocument::createElementNS('http://www.w3.org/XML/1998/namespace', 'xml:valid')
valid
29 DOMElement::__construct('xml:valid', '', 'http://www.w3.org/XML/1998/namespace')
Namespace Error
30 DOMDocument::createElementNS('http://wrong.namespaceURI.com', 'xmlns:valid')
Namespace Error
31 DOMElement::__construct('xmlns:valid', '', 'http://wrong.namespaceURI.com')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ var_dump($dom->documentURI);

?>
--EXPECTF--
string(%d) "file://%stest%20foo.html"
string(%d) "file://%stest%sfoo.html"
string(12) "php://memory"
string(16) "dummy://foo/ bar"
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ print $doc->saveXml($elt) . "\n";
$attr->removeChild($attr->firstChild);
print $doc->saveXml($elt) . "\n";

$attr->nodeValue = '&';
// Note: since libxml2 commit aca16fb3d45e0b2c45364ffc1cea8eb4abaca87d this no longer explicitly warns. This seems intentional.
@$attr->nodeValue = '&';
print "$attr->nodeValue\n";
print $doc->saveXml($elt) . "\n";

Expand All @@ -41,8 +42,6 @@ print $doc->saveXml($elt) . "\n";
<elt a="&amp;"/>
<elt a=""/>

Warning: main(): unterminated entity reference in %s on line %d

<elt a=""/>
&
<elt a="&amp;"/>
Expand Down
2 changes: 1 addition & 1 deletion ext/dom/tests/modern/xml/XMLDocument_documentURI.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ var_dump($dom->documentURI);

?>
--EXPECTF--
string(%d) "file://%stest%20foo.xml"
string(%d) "file://%stest%sfoo.xml"
2 changes: 1 addition & 1 deletion ext/dom/tests/modern/xml/XMLDocument_fromFile_02.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Dom\XMLDocument::createFromFile("\\0");

?>
--EXPECTF--
Warning: Dom\XMLDocument::createFromFile(): I/O warning : failed to load external entity "%s" in %s on line %d
Warning: Dom\XMLDocument::createFromFile(): I/O %s : failed to load %s

Fatal error: Uncaught Exception: Cannot open file '\0' in %s:%d
Stack trace:
Expand Down
22 changes: 12 additions & 10 deletions ext/libxml/libxml.c
Original file line number Diff line number Diff line change
Expand Up @@ -544,8 +544,10 @@ php_libxml_input_buffer_create_filename(const char *URI, xmlCharEncoding enc)
static xmlOutputBufferPtr
php_libxml_output_buffer_create_filename(const char *URI,
xmlCharEncodingHandlerPtr encoder,
int compression ATTRIBUTE_UNUSED)
int compression)
{
ZEND_IGNORE_VALUE(compression);

xmlOutputBufferPtr ret;
xmlURIPtr puri;
void *context = NULL;
Expand Down Expand Up @@ -841,14 +843,8 @@ PHP_LIBXML_API void php_libxml_pretend_ctx_error_ex(const char *file, int line,
/* Propagate back into libxml */
if (LIBXML(error_list)) {
xmlErrorPtr last = zend_llist_get_last(LIBXML(error_list));
if (last) {
if (!last->file) {
last->file = strdup(file);
}
/* Until there is a replacement */
ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations")
xmlCopyError(last, &xmlLastError);
ZEND_DIAGNOSTIC_IGNORED_END
if (last && !last->file) {
last->file = strdup(file);
}
}
}
Expand Down Expand Up @@ -1124,7 +1120,13 @@ PHP_FUNCTION(libxml_get_last_error)
{
ZEND_PARSE_PARAMETERS_NONE();

const xmlError *error = xmlGetLastError();
const xmlError *error;

if (LIBXML(error_list)) {
error = zend_llist_get_last(LIBXML(error_list));
} else {
error = xmlGetLastError();
}

if (error) {
php_libxml_create_error_object(return_value, error);
Expand Down
2 changes: 2 additions & 0 deletions ext/libxml/php_libxml.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,13 +258,15 @@ ZEND_TSRMLS_CACHE_EXTERN()
* Generally faster because no locking is involved, and this has the advantage that it sets the options to a known good value. */
static zend_always_inline void php_libxml_sanitize_parse_ctxt_options(xmlParserCtxtPtr ctxt)
{
ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations") \
ctxt->loadsubset = 0;
ctxt->validate = 0;
ctxt->pedantic = 0;
ctxt->replaceEntities = 0;
ctxt->linenumbers = 0;
ctxt->keepBlanks = 1;
ctxt->options = 0;
ZEND_DIAGNOSTIC_IGNORED_END
}

#else /* HAVE_LIBXML */
Expand Down
2 changes: 1 addition & 1 deletion ext/simplexml/tests/bug79971_1.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ var_dump($sxe->asXML("$uri.out%00foo"));
--EXPECTF--
Warning: simplexml_load_file(): URI must not contain percent-encoded NUL bytes in %s on line %d

Warning: simplexml_load_file(): I/O warning : failed to load external entity "%s/bug79971_1.xml%%r00%rfoo" in %s on line %d
Warning: simplexml_load_file(): I/O warning : failed to load %s
bool(false)

Warning: SimpleXMLElement::asXML(): URI must not contain percent-encoded NUL bytes in %s on line %d
Expand Down
9 changes: 7 additions & 2 deletions ext/soap/php_encoding.c
Original file line number Diff line number Diff line change
Expand Up @@ -3407,7 +3407,6 @@ xmlNsPtr encode_add_ns(xmlNodePtr node, const char* ns)
} else {
smart_str prefix = {0};
int num = ++SOAP_GLOBAL(cur_uniq_ns);
xmlChar *enc_ns;

while (1) {
smart_str_appendl(&prefix, "ns", 2);
Expand All @@ -3421,9 +3420,15 @@ xmlNsPtr encode_add_ns(xmlNodePtr node, const char* ns)
num = ++SOAP_GLOBAL(cur_uniq_ns);
}

enc_ns = xmlEncodeSpecialChars(node->doc, BAD_CAST(ns));
/* Starting with libxml 2.13, we don't have to do this workaround anymore, otherwise we get double-encoded
* entities. See libxml2 commit f506ec66547ef9bac97a2bf306d368ecea8c0c9e. */
#if LIBXML_VERSION < 21300
xmlChar *enc_ns = xmlEncodeSpecialChars(node->doc, BAD_CAST(ns));
xmlns = xmlNewNs(node->doc->children, enc_ns, BAD_CAST(prefix.s ? ZSTR_VAL(prefix.s) : ""));
xmlFree(enc_ns);
#else
xmlns = xmlNewNs(node->doc->children, BAD_CAST(ns), BAD_CAST(prefix.s ? ZSTR_VAL(prefix.s) : ""));
#endif
smart_str_free(&prefix);
}
}
Expand Down
8 changes: 7 additions & 1 deletion ext/soap/php_xml.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,16 @@ xmlDocPtr soap_xmlParseFile(const char *filename)
bool old;

php_libxml_sanitize_parse_ctxt_options(ctxt);
/* TODO: In libxml2 2.14.0 change this to the new options API so we don't rely on deprecated APIs. */
ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations")
ctxt->keepBlanks = 0;
ctxt->options |= XML_PARSE_HUGE;
ZEND_DIAGNOSTIC_IGNORED_END
ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace;
ctxt->sax->comment = soap_Comment;
ctxt->sax->warning = NULL;
ctxt->sax->error = NULL;
/*ctxt->sax->fatalError = NULL;*/
ctxt->options |= XML_PARSE_HUGE;
old = php_libxml_disable_entity_loader(1);
xmlParseDocument(ctxt);
php_libxml_disable_entity_loader(old);
Expand Down Expand Up @@ -146,7 +149,10 @@ xmlDocPtr soap_xmlParseMemory(const void *buf, size_t buf_size)
ctxt->sax->warning = NULL;
ctxt->sax->error = NULL;
/*ctxt->sax->fatalError = NULL;*/
/* TODO: In libxml2 2.14.0 change this to the new options API so we don't rely on deprecated APIs. */
ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations")
ctxt->options |= XML_PARSE_HUGE;
ZEND_DIAGNOSTIC_IGNORED_END
old = php_libxml_disable_entity_loader(1);
xmlParseDocument(ctxt);
php_libxml_disable_entity_loader(old);
Expand Down
4 changes: 2 additions & 2 deletions ext/soap/tests/bugs/bug42151.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ try {
}
echo "ok\n";
?>
--EXPECT--
SOAP-ERROR: Parsing WSDL: Couldn't load from 'httpx://' : failed to load external entity "httpx://"
--EXPECTF--
SOAP-ERROR: Parsing WSDL: Couldn't load from 'httpx://' : failed to load %s

ok
I don't get executed either.
Loading
Loading