Skip to content

Commit ecf0bb0

Browse files
committed
Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2: [ci skip] NEWS Backport libxml2 2.13.2 fixes (#14816)
2 parents bc32a6b + a5a63f2 commit ecf0bb0

22 files changed

+114
-31
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ PHP NEWS
3535
. Fixed bug GH-14775 (range function overflow with negative step argument).
3636
(David Carlier)
3737

38+
- Treewide:
39+
. Fix compatibility with libxml2 2.13.2. (nielsdos)
40+
3841
20 Jun 2024, PHP 8.3.9
3942

4043
- Core:

ext/dom/document.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,11 +1336,13 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, size_t so
13361336
if (keep_blanks == 0 && ! (options & XML_PARSE_NOBLANKS)) {
13371337
options |= XML_PARSE_NOBLANKS;
13381338
}
1339+
if (recover) {
1340+
options |= XML_PARSE_RECOVER;
1341+
}
13391342

13401343
php_libxml_sanitize_parse_ctxt_options(ctxt);
13411344
xmlCtxtUseOptions(ctxt, options);
13421345

1343-
ctxt->recovery = recover;
13441346
if (recover) {
13451347
old_error_reporting = EG(error_reporting);
13461348
EG(error_reporting) = old_error_reporting | E_WARNING;
@@ -1350,7 +1352,7 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, size_t so
13501352

13511353
if (ctxt->wellFormed || recover) {
13521354
ret = ctxt->myDoc;
1353-
if (ctxt->recovery) {
1355+
if (recover) {
13541356
EG(error_reporting) = old_error_reporting;
13551357
}
13561358
/* If loading from memory, set the base reference uri for the document */

ext/dom/tests/DOMDocument_loadHTMLfile_error1.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ $result = $doc->loadHTMLFile(__DIR__ . "/ffff/test.html");
1313
assert($result === false);
1414
?>
1515
--EXPECTF--
16-
%r(PHP ){0,1}%rWarning: DOMDocument::loadHTMLFile(): I/O warning : failed to load external entity %s
16+
%r(PHP ){0,1}%rWarning: DOMDocument::loadHTMLFile(): I/O %s

ext/dom/tests/DOMDocument_loadXML_error2_gte2_12.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ domdocumentloadxml_test_method.inc
2323
--EXPECTF--
2424
Warning: DOMDocument::loadXML(): AttValue: " or ' expected in Entity, line: 4 in %s on line %d
2525

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

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

ext/dom/tests/DOMDocument_load_error2_gte2_12.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ domdocumentload_test_method.inc
2323
--EXPECTF--
2424
Warning: DOMDocument::load(): AttValue: " or ' expected in %s on line %d
2525

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

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

ext/dom/tests/DOMDocument_relaxNGValidate_error2.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ $result = $doc->relaxNGValidate($rng);
2020
var_dump($result);
2121
?>
2222
--EXPECTF--
23-
Warning: DOMDocument::relaxNGValidate(): I/O warning : failed to load external entity "%s/foo.rng" in %s on line %d
23+
Warning: DOMDocument::relaxNGValidate(): I/O %s : failed to load %s
2424

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

ext/dom/tests/DOMDocument_saveHTMLFile_basic.phpt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ Knut Urdalen <knut@php.net>
55
#PHPTestFest2009 Norway 2009-06-09 \o/
66
--EXTENSIONS--
77
dom
8+
--SKIPIF--
9+
<?php
10+
if (LIBXML_VERSION >= 21300) die("skip see https://gitlab.gnome.org/GNOME/libxml2/-/issues/756");
11+
?>
812
--FILE--
913
<?php
1014
$filename = __DIR__."/DOMDocument_saveHTMLFile_basic.html";

ext/dom/tests/DOMDocument_saveHTMLFile_formatOutput.phpt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ Knut Urdalen <knut@php.net>
55
#PHPTestFest2009 Norway 2009-06-09 \o/
66
--EXTENSIONS--
77
dom
8+
--SKIPIF--
9+
<?php
10+
if (LIBXML_VERSION >= 21300) die("skip see https://gitlab.gnome.org/GNOME/libxml2/-/issues/756");
11+
?>
812
--FILE--
913
<?php
1014
$filename = __DIR__."/DOMDocument_saveHTMLFile_formatOutput.html";
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
DOMDocument::saveHTMLFile() should format output on demand
3+
--CREDITS--
4+
Knut Urdalen <knut@php.net>
5+
#PHPTestFest2009 Norway 2009-06-09 \o/
6+
--EXTENSIONS--
7+
dom
8+
--SKIPIF--
9+
<?php
10+
if (LIBXML_VERSION < 21300) die("skip see https://gitlab.gnome.org/GNOME/libxml2/-/issues/756");
11+
?>
12+
--FILE--
13+
<?php
14+
$filename = __DIR__."/DOMDocument_saveHTMLFile_formatOutput_gte_2_13.html";
15+
$doc = new DOMDocument('1.0');
16+
$doc->formatOutput = true;
17+
$root = $doc->createElement('html');
18+
$root = $doc->appendChild($root);
19+
$head = $doc->createElement('head');
20+
$head = $root->appendChild($head);
21+
$title = $doc->createElement('title');
22+
$title = $head->appendChild($title);
23+
$text = $doc->createTextNode('This is the title');
24+
$text = $title->appendChild($text);
25+
$bytes = $doc->saveHTMLFile($filename);
26+
var_dump($bytes);
27+
echo file_get_contents($filename);
28+
unlink($filename);
29+
?>
30+
--EXPECT--
31+
int(59)
32+
<html><head><title>This is the title</title></head></html>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
DOMDocument::saveHTMLFile() should dump the internal document into a file using HTML formatting
3+
--CREDITS--
4+
Knut Urdalen <knut@php.net>
5+
#PHPTestFest2009 Norway 2009-06-09 \o/
6+
--EXTENSIONS--
7+
dom
8+
--SKIPIF--
9+
<?php
10+
if (LIBXML_VERSION < 21300) die("skip see https://gitlab.gnome.org/GNOME/libxml2/-/issues/756");
11+
?>
12+
--FILE--
13+
<?php
14+
$filename = __DIR__."/DOMDocument_saveHTMLFile_basic_gte_2_13.html";
15+
$doc = new DOMDocument('1.0');
16+
$root = $doc->createElement('html');
17+
$root = $doc->appendChild($root);
18+
$head = $doc->createElement('head');
19+
$head = $root->appendChild($head);
20+
$title = $doc->createElement('title');
21+
$title = $head->appendChild($title);
22+
$text = $doc->createTextNode('This is the title');
23+
$text = $title->appendChild($text);
24+
$bytes = $doc->saveHTMLFile($filename);
25+
var_dump($bytes);
26+
echo file_get_contents($filename);
27+
unlink($filename);
28+
?>
29+
--EXPECT--
30+
int(59)
31+
<html><head><title>This is the title</title></head></html>

ext/dom/tests/DOMDocument_schemaValidate_error5.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ var_dump($result);
1717

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

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

ext/dom/tests/DOMElement_insertAdjacentText.phpt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ echo $dom->saveXML($empty), "\n";
5151
$AText = $empty->firstChild;
5252
$empty->insertAdjacentText("afterbegin", 'B');
5353
echo $dom->saveXML($empty), "\n";
54-
var_dump($AText->textContent);
5554

5655
?>
5756
--EXPECT--
@@ -78,4 +77,3 @@ Syntax Error
7877
--- Normal cases starting from empty element ---
7978
<empty>A</empty>
8079
<empty>BA</empty>
81-
string(2) "BA"

ext/dom/tests/DOMEntityReference_predefined_free.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ dom
77
$ref = new DOMEntityReference("amp");
88
var_dump($ref);
99
?>
10-
--EXPECT--
10+
--EXPECTF--
1111
object(DOMEntityReference)#1 (17) {
1212
["nodeName"]=>
1313
string(3) "amp"
@@ -42,5 +42,5 @@ object(DOMEntityReference)#1 (17) {
4242
["baseURI"]=>
4343
NULL
4444
["textContent"]=>
45-
string(0) ""
45+
string(%d) "%S"
4646
}

ext/dom/tests/dom_create_element.phpt

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -251,14 +251,10 @@ try {
251251
print $e->getMessage() . "\n";
252252
}
253253

254-
/* This isn't because the xml namespace isn't there and we can't create it */
255-
print "29 DOMElement::__construct('xml:valid', '', 'http://www.w3.org/XML/1998/namespace')\n";
256-
try {
257-
$element = new DomElement('xml:valid', '', 'http://www.w3.org/XML/1998/namespace');
258-
print "valid\n";
259-
} catch (Exception $e) {
260-
print $e->getMessage() . "\n";
261-
}
254+
/* There used to be a 29 here that tested DOMElement::__construct('xml:valid', '', 'http://www.w3.org/XML/1998/namespace').
255+
* 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
256+
* a document. Starting from libxml2 version 2.13 it does actually work because the XML namespace is statically defined.
257+
* The behaviour from version 2.13 is actually the desired behaviour anyway. */
262258

263259

264260
/* the qualifiedName or its prefix is "xmlns" and the namespaceURI is
@@ -378,8 +374,6 @@ Namespace Error
378374
Namespace Error
379375
28 DOMDocument::createElementNS('http://www.w3.org/XML/1998/namespace', 'xml:valid')
380376
valid
381-
29 DOMElement::__construct('xml:valid', '', 'http://www.w3.org/XML/1998/namespace')
382-
Namespace Error
383377
30 DOMDocument::createElementNS('http://wrong.namespaceURI.com', 'xmlns:valid')
384378
Namespace Error
385379
31 DOMElement::__construct('xmlns:valid', '', 'http://wrong.namespaceURI.com')

ext/libxml/libxml.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,8 +580,10 @@ php_libxml_input_buffer_create_filename(const char *URI, xmlCharEncoding enc)
580580
static xmlOutputBufferPtr
581581
php_libxml_output_buffer_create_filename(const char *URI,
582582
xmlCharEncodingHandlerPtr encoder,
583-
int compression ATTRIBUTE_UNUSED)
583+
int compression)
584584
{
585+
ZEND_IGNORE_VALUE(compression);
586+
585587
xmlOutputBufferPtr ret;
586588
xmlURIPtr puri;
587589
void *context = NULL;

ext/libxml/php_libxml.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,13 +197,15 @@ ZEND_TSRMLS_CACHE_EXTERN()
197197
* Generally faster because no locking is involved, and this has the advantage that it sets the options to a known good value. */
198198
static zend_always_inline void php_libxml_sanitize_parse_ctxt_options(xmlParserCtxtPtr ctxt)
199199
{
200+
PHP_LIBXML_IGNORE_DEPRECATIONS_START
200201
ctxt->loadsubset = 0;
201202
ctxt->validate = 0;
202203
ctxt->pedantic = 0;
203204
ctxt->replaceEntities = 0;
204205
ctxt->linenumbers = 0;
205206
ctxt->keepBlanks = 1;
206207
ctxt->options = 0;
208+
PHP_LIBXML_IGNORE_DEPRECATIONS_END
207209
}
208210

209211
#else /* HAVE_LIBXML */

ext/simplexml/tests/bug79971_1.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ var_dump($sxe->asXML("$uri.out%00foo"));
2222
--EXPECTF--
2323
Warning: simplexml_load_file(): URI must not contain percent-encoded NUL bytes in %s on line %d
2424

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

2828
Warning: SimpleXMLElement::asXML(): URI must not contain percent-encoded NUL bytes in %s on line %d

ext/soap/php_encoding.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3381,7 +3381,6 @@ xmlNsPtr encode_add_ns(xmlNodePtr node, const char* ns)
33813381
} else {
33823382
smart_str prefix = {0};
33833383
int num = ++SOAP_GLOBAL(cur_uniq_ns);
3384-
xmlChar *enc_ns;
33853384

33863385
while (1) {
33873386
smart_str_appendl(&prefix, "ns", 2);
@@ -3395,9 +3394,15 @@ xmlNsPtr encode_add_ns(xmlNodePtr node, const char* ns)
33953394
num = ++SOAP_GLOBAL(cur_uniq_ns);
33963395
}
33973396

3398-
enc_ns = xmlEncodeSpecialChars(node->doc, BAD_CAST(ns));
3397+
/* Starting with libxml 2.13, we don't have to do this workaround anymore, otherwise we get double-encoded
3398+
* entities. See libxml2 commit f506ec66547ef9bac97a2bf306d368ecea8c0c9e. */
3399+
#if LIBXML_VERSION < 21300
3400+
xmlChar *enc_ns = xmlEncodeSpecialChars(node->doc, BAD_CAST(ns));
33993401
xmlns = xmlNewNs(node->doc->children, enc_ns, BAD_CAST(prefix.s ? ZSTR_VAL(prefix.s) : ""));
34003402
xmlFree(enc_ns);
3403+
#else
3404+
xmlns = xmlNewNs(node->doc->children, BAD_CAST(ns), BAD_CAST(prefix.s ? ZSTR_VAL(prefix.s) : ""));
3405+
#endif
34013406
smart_str_free(&prefix);
34023407
}
34033408
}

ext/soap/php_xml.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,16 @@ xmlDocPtr soap_xmlParseFile(const char *filename)
9292
bool old;
9393

9494
php_libxml_sanitize_parse_ctxt_options(ctxt);
95+
/* TODO: In libxml2 2.14.0 change this to the new options API so we don't rely on deprecated APIs. */
96+
PHP_LIBXML_IGNORE_DEPRECATIONS_START
9597
ctxt->keepBlanks = 0;
98+
ctxt->options |= XML_PARSE_HUGE;
99+
PHP_LIBXML_IGNORE_DEPRECATIONS_END
96100
ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace;
97101
ctxt->sax->comment = soap_Comment;
98102
ctxt->sax->warning = NULL;
99103
ctxt->sax->error = NULL;
100104
/*ctxt->sax->fatalError = NULL;*/
101-
ctxt->options |= XML_PARSE_HUGE;
102105
old = php_libxml_disable_entity_loader(1);
103106
xmlParseDocument(ctxt);
104107
php_libxml_disable_entity_loader(old);
@@ -146,7 +149,10 @@ xmlDocPtr soap_xmlParseMemory(const void *buf, size_t buf_size)
146149
ctxt->sax->warning = NULL;
147150
ctxt->sax->error = NULL;
148151
/*ctxt->sax->fatalError = NULL;*/
152+
/* TODO: In libxml2 2.14.0 change this to the new options API so we don't rely on deprecated APIs. */
153+
PHP_LIBXML_IGNORE_DEPRECATIONS_START
149154
ctxt->options |= XML_PARSE_HUGE;
155+
PHP_LIBXML_IGNORE_DEPRECATIONS_END
150156
old = php_libxml_disable_entity_loader(1);
151157
xmlParseDocument(ctxt);
152158
php_libxml_disable_entity_loader(old);

ext/soap/tests/bugs/bug42151.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ try {
2525
}
2626
echo "ok\n";
2727
?>
28-
--EXPECT--
29-
SOAP-ERROR: Parsing WSDL: Couldn't load from 'httpx://' : failed to load external entity "httpx://"
28+
--EXPECTF--
29+
SOAP-ERROR: Parsing WSDL: Couldn't load from 'httpx://' : failed to load %s
3030

3131
ok
3232
I don't get executed either.

ext/xml/compat.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -714,8 +714,7 @@ XML_GetCurrentByteCount(XML_Parser parser)
714714
{
715715
/* WARNING: this is identical to ByteIndex; it should probably
716716
* be different */
717-
return parser->parser->input->consumed +
718-
(parser->parser->input->cur - parser->parser->input->base);
717+
return XML_GetCurrentByteIndex(parser);
719718
}
720719

721720
PHP_XML_API const XML_Char *XML_ExpatVersion(void)

ext/xmlwriter/php_xmlwriter.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -900,7 +900,8 @@ static void php_xmlwriter_flush(INTERNAL_FUNCTION_PARAMETERS, int force_string)
900900
}
901901
output_bytes = xmlTextWriterFlush(ptr);
902902
if (buffer) {
903-
RETVAL_STRING((char *) buffer->content);
903+
const xmlChar *content = xmlBufferContent(buffer);
904+
RETVAL_STRING((const char *) content);
904905
if (empty) {
905906
xmlBufferEmpty(buffer);
906907
}

0 commit comments

Comments
 (0)