Bug #68437 [Opn]: saveXML produces invalid xml
| From: | cmb@php.net | Date: | Tue, 18 Aug 2015 20:53:21 +0000 |
| Subject: | Bug #68437 [Opn]: saveXML produces invalid xml | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-195309@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=68437&edit=1
ID: 68437
Updated by: cmb@php.net
Reported by: lphp-bug at thax dot hardliners dot org
Summary: saveXML produces invalid xml
Status: Open
Type: Bug
Package: DOM XML related
PHP Version: master-Git-2014-11-17 (Git)
Block user comment: N
Private report: N
New Comment:
> XML (even the 1998 working drafts) defines valid chars as:
> Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
That was XML 1.0[1]. However, XML 1.1[2] defines:
Char ::= [#x1-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
[1] <http://www.w3.org/TR/REC-xml/#charsets>
[2] <http://www.w3.org/TR/xml11/#charsets>
Previous Comments:
------------------------------------------------------------------------
[2014-11-17 18:50:43] lphp-bug at thax dot hardliners dot org
Description:
------------
Bug #54214 has been closed as Bogus, but gets the facts wrong:
1. XML (even the 1998 working drafts) defines valid chars as:
Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
This contradicts #54214 that Char ::= [#x1-#xD7FF] | ...
Thus, 0x0b (or 0x06) are actually not in the valid Range.
2. libxml2 "problem" is not saving low-ascii chars, but loading them: loadXML(saveXML())
ALWAYS fails, when e.g. DOMText with low-ascii is present:
DOMDocument::loadXML(): xmlParseCharRef: invalid xmlChar value 11 in Entity
3. saveXML() does not always warn.
More specifically, it only warns when
(*) $doc has no encoding AND
(**) saveXML() is called without arguments.
4. When saveXML() does warn, it will remove the offending character (good), but not when it does not
warn.
Background:
- saveXML() uses xmlDocDumpFormatMemory(), which uses document encoding, when given. Otherwise ascii
encoding (0x00 ... 0x7f only) is assumed, and xmlEscapeEntities (libxml2/tree/xmlsave.c, line 208)
is used as escape-function.
This function warns and ignores the offending character
- saveXML($el) uses xmlNodeDump(), which passes encoding==NULL to xmlNodeDumpOuput, which converts
NULL to "UTF-8". Then xmlSaveCtxtInit() will not set the escape-function.
When the escape-function is not set on the xmlSaveCtxt, xmlOutputBufferWriteEscape will use
xmlEscapeContent (libxml2/tree/xmlIO.c, line 3536) instead. This function does not warn, and happily
includes 0x0b in the output (where finally loadXML chokes on it).
Libxml never says that it will warn for low-ascii chars. Thus php-developers can't depend on
it.
OTOH, it's unfeasible to force every php-programmer to pre-sanitize strings sent into DOMText,
or post-check the saved xml string. Therefore php has to provide the necessary means to avoid
invalid xmls -- i.e. at the very least warn, or even better: throw already in DOMText.
Test script:
---------------
$doc=new DOMDocument('1.0','utf-8'); // or: $doc=new
DOMDocument('1.0'); (*)
$el=$doc->createElement('root');
$doc->appendChild($el);
$el->appendChild(new DOMText("\x0b asdf"));
$str=$doc->saveXML($el); // or: $doc->saveXML() (**)
var_dump($str);
$doc->loadXML($str);
Expected result:
----------------
loadXML shall load the saved xml, or throw an exception earlier.
Actual result:
--------------
loadXML only works when (*) and (**) are used, i.e. when saveXML outputs a warning.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=68437&edit=1