aboutsummaryrefslogtreecommitdiffstats
path: root/meta
diff options
context:
space:
mode:
authorAndrej Valek <andrej.valek@siemens.com>2017-06-14 14:38:35 +0200
committerRichard Purdie <richard.purdie@linuxfoundation.org>2017-06-23 11:43:38 +0100
commit4651afdd457eca06da07331186bf28b98df2eeff (patch)
treea169eb72c097ea3d179bd587b4820ceecf7fe51e /meta
parente3985be0ddb40e8db44422092c875a4e373a6da3 (diff)
downloadopenembedded-core-contrib-4651afdd457eca06da07331186bf28b98df2eeff.tar.gz
libxml2: Avoid reparsing and simplify control flow in xmlParseStartTag2
Signed-off-by: Andrej Valek <andrej.valek@siemens.com>
Diffstat (limited to 'meta')
-rw-r--r--meta/recipes-core/libxml/libxml2/libxml2-fix_and_simplify_xmlParseStartTag2.patch590
-rw-r--r--meta/recipes-core/libxml/libxml2_2.9.4.bb1
2 files changed, 591 insertions, 0 deletions
diff --git a/meta/recipes-core/libxml/libxml2/libxml2-fix_and_simplify_xmlParseStartTag2.patch b/meta/recipes-core/libxml/libxml2/libxml2-fix_and_simplify_xmlParseStartTag2.patch
new file mode 100644
index 0000000000..faa57701f5
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/libxml2-fix_and_simplify_xmlParseStartTag2.patch
@@ -0,0 +1,590 @@
+libxml2-2.9.4: Avoid reparsing and simplify control flow in xmlParseStartTag2
+
+[No upstream tracking]
+
+parser: Avoid reparsing in xmlParseStartTag2
+
+The code in xmlParseStartTag2 must handle the case that the input
+buffer was grown and reallocated which can invalidate pointers to
+attribute values. Before, this was handled by detecting changes of
+the input buffer "base" pointer and, in case of a change, jumping
+back to the beginning of the function and reparsing the start tag.
+
+The major problem of this approach is that whether an input buffer is
+reallocated is nondeterministic, resulting in seemingly random test
+failures. See the mailing list thread "runtest mystery bug: name2.xml
+error case regression test" from 2012, for example.
+
+If a reallocation was detected, the code also made no attempts to
+continue parsing in case of errors which makes a difference in
+the lax "recover" mode.
+
+Now we store the current input buffer "base" pointer for each (not
+separately allocated) attribute in the namespace URI field, which isn't
+used until later. After the whole start tag was parsed, the pointers to
+the attribute values are reconstructed using the offset between the
+new and the old input buffer. This relies on arithmetic on dangling
+pointers which is technically undefined behavior. But it seems like
+the easiest and most efficient fix and a similar approach is used in
+xmlParserInputGrow.
+
+This changes the error output of several tests, typically making it
+more verbose because we try harder to continue parsing in case of errors.
+
+(Another possible solution is to check not only the "base" pointer
+but the size of the input buffer as well. But this would result in
+even more reparsing.)
+
+Remove some goto labels and deduplicate a bit of code after handling
+namespaces.
+
+There were two bugs where parameter-entity references could lead to an
+unexpected change of the input buffer in xmlParseNameComplex and
+xmlDictLookup being called with an invalid pointer.
+
+
+Upstream-Status: Backport
+ - [https://git.gnome.org/browse/libxml2/commit/?id=07b7428b69c368611d215a140fe630b2d1e61349]
+ - [https://git.gnome.org/browse/libxml2/commit/?id=855c19efb7cd30d927d673b3658563c4959ca6f0]
+Signed-off-by: Andrej Valek <andrej.valek@siemens.com>
+
+diff --git a/parser.c b/parser.c
+index 609a270..74016e3 100644
+--- a/parser.c
++++ b/parser.c
+@@ -43,6 +43,7 @@
+ #include <limits.h>
+ #include <string.h>
+ #include <stdarg.h>
++#include <stddef.h>
+ #include <libxml/xmlmemory.h>
+ #include <libxml/threads.h>
+ #include <libxml/globals.h>
+@@ -9377,8 +9378,7 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
+ const xmlChar **atts = ctxt->atts;
+ int maxatts = ctxt->maxatts;
+ int nratts, nbatts, nbdef;
+- int i, j, nbNs, attval, oldline, oldcol, inputNr;
+- const xmlChar *base;
++ int i, j, nbNs, attval;
+ unsigned long cur;
+ int nsNr = ctxt->nsNr;
+
+@@ -9392,13 +9392,8 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
+ * The Shrinking is only possible once the full set of attribute
+ * callbacks have been done.
+ */
+-reparse:
+ SHRINK;
+- base = ctxt->input->base;
+ cur = ctxt->input->cur - ctxt->input->base;
+- inputNr = ctxt->inputNr;
+- oldline = ctxt->input->line;
+- oldcol = ctxt->input->col;
+ nbatts = 0;
+ nratts = 0;
+ nbdef = 0;
+@@ -9422,8 +9417,6 @@ reparse:
+ */
+ SKIP_BLANKS;
+ GROW;
+- if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr))
+- goto base_changed;
+
+ while (((RAW != '>') &&
+ ((RAW != '/') || (NXT(1) != '>')) &&
+@@ -9434,203 +9427,174 @@ reparse:
+
+ attname = xmlParseAttribute2(ctxt, prefix, localname,
+ &aprefix, &attvalue, &len, &alloc);
+- if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr)) {
+- if ((attvalue != NULL) && (alloc != 0))
+- xmlFree(attvalue);
+- attvalue = NULL;
+- goto base_changed;
+- }
+- if ((attname != NULL) && (attvalue != NULL)) {
+- if (len < 0) len = xmlStrlen(attvalue);
+- if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
+- const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
+- xmlURIPtr uri;
+-
+- if (URL == NULL) {
+- xmlErrMemory(ctxt, "dictionary allocation failure");
+- if ((attvalue != NULL) && (alloc != 0))
+- xmlFree(attvalue);
+- return(NULL);
+- }
+- if (*URL != 0) {
+- uri = xmlParseURI((const char *) URL);
+- if (uri == NULL) {
+- xmlNsErr(ctxt, XML_WAR_NS_URI,
+- "xmlns: '%s' is not a valid URI\n",
+- URL, NULL, NULL);
+- } else {
+- if (uri->scheme == NULL) {
+- xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
+- "xmlns: URI %s is not absolute\n",
+- URL, NULL, NULL);
+- }
+- xmlFreeURI(uri);
+- }
+- if (URL == ctxt->str_xml_ns) {
+- if (attname != ctxt->str_xml) {
+- xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
+- "xml namespace URI cannot be the default namespace\n",
+- NULL, NULL, NULL);
+- }
+- goto skip_default_ns;
+- }
+- if ((len == 29) &&
+- (xmlStrEqual(URL,
+- BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
+- xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
+- "reuse of the xmlns namespace name is forbidden\n",
+- NULL, NULL, NULL);
+- goto skip_default_ns;
+- }
+- }
+- /*
+- * check that it's not a defined namespace
+- */
+- for (j = 1;j <= nbNs;j++)
+- if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
+- break;
+- if (j <= nbNs)
+- xmlErrAttributeDup(ctxt, NULL, attname);
+- else
+- if (nsPush(ctxt, NULL, URL) > 0) nbNs++;
+-skip_default_ns:
+- if ((attvalue != NULL) && (alloc != 0)) {
+- xmlFree(attvalue);
+- attvalue = NULL;
+- }
+- if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
+- break;
+- if (!IS_BLANK_CH(RAW)) {
+- xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+- "attributes construct error\n");
+- break;
+- }
+- SKIP_BLANKS;
+- if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr))
+- goto base_changed;
+- continue;
+- }
+- if (aprefix == ctxt->str_xmlns) {
+- const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
+- xmlURIPtr uri;
+-
+- if (attname == ctxt->str_xml) {
+- if (URL != ctxt->str_xml_ns) {
+- xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
+- "xml namespace prefix mapped to wrong URI\n",
+- NULL, NULL, NULL);
+- }
+- /*
+- * Do not keep a namespace definition node
+- */
+- goto skip_ns;
+- }
++ if ((attname == NULL) || (attvalue == NULL))
++ goto next_attr;
++ if (len < 0) len = xmlStrlen(attvalue);
++
++ if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
++ const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
++ xmlURIPtr uri;
++
++ if (URL == NULL) {
++ xmlErrMemory(ctxt, "dictionary allocation failure");
++ if ((attvalue != NULL) && (alloc != 0))
++ xmlFree(attvalue);
++ return(NULL);
++ }
++ if (*URL != 0) {
++ uri = xmlParseURI((const char *) URL);
++ if (uri == NULL) {
++ xmlNsErr(ctxt, XML_WAR_NS_URI,
++ "xmlns: '%s' is not a valid URI\n",
++ URL, NULL, NULL);
++ } else {
++ if (uri->scheme == NULL) {
++ xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
++ "xmlns: URI %s is not absolute\n",
++ URL, NULL, NULL);
++ }
++ xmlFreeURI(uri);
++ }
+ if (URL == ctxt->str_xml_ns) {
+- if (attname != ctxt->str_xml) {
+- xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
+- "xml namespace URI mapped to wrong prefix\n",
+- NULL, NULL, NULL);
+- }
+- goto skip_ns;
+- }
+- if (attname == ctxt->str_xmlns) {
+- xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
+- "redefinition of the xmlns prefix is forbidden\n",
+- NULL, NULL, NULL);
+- goto skip_ns;
+- }
+- if ((len == 29) &&
+- (xmlStrEqual(URL,
+- BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
+- xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
+- "reuse of the xmlns namespace name is forbidden\n",
+- NULL, NULL, NULL);
+- goto skip_ns;
+- }
+- if ((URL == NULL) || (URL[0] == 0)) {
+- xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
+- "xmlns:%s: Empty XML namespace is not allowed\n",
+- attname, NULL, NULL);
+- goto skip_ns;
+- } else {
+- uri = xmlParseURI((const char *) URL);
+- if (uri == NULL) {
+- xmlNsErr(ctxt, XML_WAR_NS_URI,
+- "xmlns:%s: '%s' is not a valid URI\n",
+- attname, URL, NULL);
+- } else {
+- if ((ctxt->pedantic) && (uri->scheme == NULL)) {
+- xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
+- "xmlns:%s: URI %s is not absolute\n",
+- attname, URL, NULL);
+- }
+- xmlFreeURI(uri);
+- }
+- }
+-
+- /*
+- * check that it's not a defined namespace
+- */
+- for (j = 1;j <= nbNs;j++)
+- if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
+- break;
+- if (j <= nbNs)
+- xmlErrAttributeDup(ctxt, aprefix, attname);
+- else
+- if (nsPush(ctxt, attname, URL) > 0) nbNs++;
+-skip_ns:
+- if ((attvalue != NULL) && (alloc != 0)) {
+- xmlFree(attvalue);
+- attvalue = NULL;
+- }
+- if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
+- break;
+- if (!IS_BLANK_CH(RAW)) {
+- xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+- "attributes construct error\n");
+- break;
+- }
+- SKIP_BLANKS;
+- if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr))
+- goto base_changed;
+- continue;
+- }
++ if (attname != ctxt->str_xml) {
++ xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
++ "xml namespace URI cannot be the default namespace\n",
++ NULL, NULL, NULL);
++ }
++ goto next_attr;
++ }
++ if ((len == 29) &&
++ (xmlStrEqual(URL,
++ BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
++ xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
++ "reuse of the xmlns namespace name is forbidden\n",
++ NULL, NULL, NULL);
++ goto next_attr;
++ }
++ }
++ /*
++ * check that it's not a defined namespace
++ */
++ for (j = 1;j <= nbNs;j++)
++ if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
++ break;
++ if (j <= nbNs)
++ xmlErrAttributeDup(ctxt, NULL, attname);
++ else
++ if (nsPush(ctxt, NULL, URL) > 0) nbNs++;
++
++ } else if (aprefix == ctxt->str_xmlns) {
++ const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
++ xmlURIPtr uri;
++
++ if (attname == ctxt->str_xml) {
++ if (URL != ctxt->str_xml_ns) {
++ xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
++ "xml namespace prefix mapped to wrong URI\n",
++ NULL, NULL, NULL);
++ }
++ /*
++ * Do not keep a namespace definition node
++ */
++ goto next_attr;
++ }
++ if (URL == ctxt->str_xml_ns) {
++ if (attname != ctxt->str_xml) {
++ xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
++ "xml namespace URI mapped to wrong prefix\n",
++ NULL, NULL, NULL);
++ }
++ goto next_attr;
++ }
++ if (attname == ctxt->str_xmlns) {
++ xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
++ "redefinition of the xmlns prefix is forbidden\n",
++ NULL, NULL, NULL);
++ goto next_attr;
++ }
++ if ((len == 29) &&
++ (xmlStrEqual(URL,
++ BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
++ xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
++ "reuse of the xmlns namespace name is forbidden\n",
++ NULL, NULL, NULL);
++ goto next_attr;
++ }
++ if ((URL == NULL) || (URL[0] == 0)) {
++ xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
++ "xmlns:%s: Empty XML namespace is not allowed\n",
++ attname, NULL, NULL);
++ goto next_attr;
++ } else {
++ uri = xmlParseURI((const char *) URL);
++ if (uri == NULL) {
++ xmlNsErr(ctxt, XML_WAR_NS_URI,
++ "xmlns:%s: '%s' is not a valid URI\n",
++ attname, URL, NULL);
++ } else {
++ if ((ctxt->pedantic) && (uri->scheme == NULL)) {
++ xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
++ "xmlns:%s: URI %s is not absolute\n",
++ attname, URL, NULL);
++ }
++ xmlFreeURI(uri);
++ }
++ }
+
+- /*
+- * Add the pair to atts
+- */
+- if ((atts == NULL) || (nbatts + 5 > maxatts)) {
+- if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
+- if (attvalue[len] == 0)
+- xmlFree(attvalue);
+- goto failed;
+- }
+- maxatts = ctxt->maxatts;
+- atts = ctxt->atts;
+- }
+- ctxt->attallocs[nratts++] = alloc;
+- atts[nbatts++] = attname;
+- atts[nbatts++] = aprefix;
+- atts[nbatts++] = NULL; /* the URI will be fetched later */
+- atts[nbatts++] = attvalue;
+- attvalue += len;
+- atts[nbatts++] = attvalue;
+- /*
+- * tag if some deallocation is needed
+- */
+- if (alloc != 0) attval = 1;
+- } else {
+- if ((attvalue != NULL) && (attvalue[len] == 0))
+- xmlFree(attvalue);
+- }
++ /*
++ * check that it's not a defined namespace
++ */
++ for (j = 1;j <= nbNs;j++)
++ if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
++ break;
++ if (j <= nbNs)
++ xmlErrAttributeDup(ctxt, aprefix, attname);
++ else
++ if (nsPush(ctxt, attname, URL) > 0) nbNs++;
++
++ } else {
++ /*
++ * Add the pair to atts
++ */
++ if ((atts == NULL) || (nbatts + 5 > maxatts)) {
++ if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
++ goto next_attr;
++ }
++ maxatts = ctxt->maxatts;
++ atts = ctxt->atts;
++ }
++ ctxt->attallocs[nratts++] = alloc;
++ atts[nbatts++] = attname;
++ atts[nbatts++] = aprefix;
++ /*
++ * The namespace URI field is used temporarily to point at the
++ * base of the current input buffer for non-alloced attributes.
++ * When the input buffer is reallocated, all the pointers become
++ * invalid, but they can be reconstructed later.
++ */
++ if (alloc)
++ atts[nbatts++] = NULL;
++ else
++ atts[nbatts++] = ctxt->input->base;
++ atts[nbatts++] = attvalue;
++ attvalue += len;
++ atts[nbatts++] = attvalue;
++ /*
++ * tag if some deallocation is needed
++ */
++ if (alloc != 0) attval = 1;
++ attvalue = NULL; /* moved into atts */
++ }
+
+-failed:
++next_attr:
++ if ((attvalue != NULL) && (alloc != 0)) {
++ xmlFree(attvalue);
++ attvalue = NULL;
++ }
+
+ GROW
+ if (ctxt->instate == XML_PARSER_EOF)
+ break;
+- if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr))
+- goto base_changed;
+ if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
+ break;
+ if (!IS_BLANK_CH(RAW)) {
+@@ -9646,8 +9610,20 @@ failed:
+ break;
+ }
+ GROW;
+- if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr))
+- goto base_changed;
++ }
++
++ /* Reconstruct attribute value pointers. */
++ for (i = 0, j = 0; j < nratts; i += 5, j++) {
++ if (atts[i+2] != NULL) {
++ /*
++ * Arithmetic on dangling pointers is technically undefined
++ * behavior, but well...
++ */
++ ptrdiff_t offset = ctxt->input->base - atts[i+2];
++ atts[i+2] = NULL; /* Reset repurposed namespace URI */
++ atts[i+3] += offset; /* value */
++ atts[i+4] += offset; /* valuend */
++ }
+ }
+
+ /*
+@@ -9804,34 +9780,6 @@ failed:
+ }
+
+ return(localname);
+-
+-base_changed:
+- /*
+- * the attribute strings are valid iif the base didn't changed
+- */
+- if (attval != 0) {
+- for (i = 3,j = 0; j < nratts;i += 5,j++)
+- if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
+- xmlFree((xmlChar *) atts[i]);
+- }
+-
+- /*
+- * We can't switch from one entity to another in the middle
+- * of a start tag
+- */
+- if (inputNr != ctxt->inputNr) {
+- xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+- "Start tag doesn't start and stop in the same entity\n");
+- return(NULL);
+- }
+-
+- ctxt->input->cur = ctxt->input->base + cur;
+- ctxt->input->line = oldline;
+- ctxt->input->col = oldcol;
+- if (ctxt->wellFormed == 1) {
+- goto reparse;
+- }
+- return(NULL);
+ }
+
+ /**
+diff --git a/result/errors/759398.xml.err b/result/errors/759398.xml.err
+index e08d9bf..f6036a3 100644
+--- a/result/errors/759398.xml.err
++++ b/result/errors/759398.xml.err
+@@ -1,9 +1,12 @@
+ ./test/errors/759398.xml:210: parser error : StartTag: invalid element name
+ need to worry about parsers whi<! don't expand PErefs finding
+ ^
+-./test/errors/759398.xml:309: parser error : Opening and ending tag mismatch: spec line 50 and termdef
++./test/errors/759398.xml:309: parser error : Opening and ending tag mismatch: №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№m line 308 and termdef
+ and provide access to their content and structure.</termdef> <termdef
+ ^
+-./test/errors/759398.xml:309: parser error : Extra content at the end of the document
+-and provide access to their content and structure.</termdef> <termdef
+- ^
++./test/errors/759398.xml:314: parser error : Opening and ending tag mismatch: spec line 50 and p
++data and the information it must provide to the application.</p>
++ ^
++./test/errors/759398.xml:316: parser error : Extra content at the end of the document
++<div2 id='sec-origin-goals'>
++^
+diff --git a/result/errors/attr1.xml.err b/result/errors/attr1.xml.err
+index 4f08538..c4c4fc8 100644
+--- a/result/errors/attr1.xml.err
++++ b/result/errors/attr1.xml.err
+@@ -1,6 +1,9 @@
+ ./test/errors/attr1.xml:2: parser error : AttValue: ' expected
+
+ ^
+-./test/errors/attr1.xml:1: parser error : Extra content at the end of the document
+-<foo foo="oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
+- ^
++./test/errors/attr1.xml:2: parser error : attributes construct error
++
++^
++./test/errors/attr1.xml:2: parser error : Couldn't find end of Start Tag foo line 1
++
++^
+diff --git a/result/errors/attr2.xml.err b/result/errors/attr2.xml.err
+index c8a9c7d..77e342e 100644
+--- a/result/errors/attr2.xml.err
++++ b/result/errors/attr2.xml.err
+@@ -1,6 +1,9 @@
+ ./test/errors/attr2.xml:2: parser error : AttValue: ' expected
+
+ ^
+-./test/errors/attr2.xml:1: parser error : Extra content at the end of the document
+-<foo foo=">ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
+- ^
++./test/errors/attr2.xml:2: parser error : attributes construct error
++
++^
++./test/errors/attr2.xml:2: parser error : Couldn't find end of Start Tag foo line 1
++
++^
+diff --git a/result/errors/name2.xml.err b/result/errors/name2.xml.err
+index a6649a1..8a6acee 100644
+--- a/result/errors/name2.xml.err
++++ b/result/errors/name2.xml.err
+@@ -1,6 +1,9 @@
+ ./test/errors/name2.xml:2: parser error : Specification mandate value for attribute foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
+
+ ^
+-./test/errors/name2.xml:1: parser error : Extra content at the end of the document
+-<foo foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
+- ^
++./test/errors/name2.xml:2: parser error : attributes construct error
++
++^
++./test/errors/name2.xml:2: parser error : Couldn't find end of Start Tag foo line 1
++
++^
diff --git a/meta/recipes-core/libxml/libxml2_2.9.4.bb b/meta/recipes-core/libxml/libxml2_2.9.4.bb
index 4f60781d22..0577ad6509 100644
--- a/meta/recipes-core/libxml/libxml2_2.9.4.bb
+++ b/meta/recipes-core/libxml/libxml2_2.9.4.bb
@@ -23,6 +23,7 @@ SRC_URI = "ftp://xmlsoft.org/libxml2/libxml2-${PV}.tar.gz;name=libtar \
file://libxml2-CVE-2016-5131.patch \
file://libxml2-CVE-2016-4658.patch \
file://libxml2-fix_NULL_pointer_derefs.patch \
+ file://libxml2-fix_and_simplify_xmlParseStartTag2.patch \
file://CVE-2016-9318.patch \
file://0001-Make-ptest-run-the-python-tests-if-python-is-enabled.patch \
"