diff --git a/Check-for-overflow-when-allocating-two-dimensional-a.patch b/Check-for-overflow-when-allocating-two-dimensional-a.patch new file mode 100644 index 0000000000000000000000000000000000000000..f34757c3c90a2ea80063544914abf0535007133b --- /dev/null +++ b/Check-for-overflow-when-allocating-two-dimensional-a.patch @@ -0,0 +1,105 @@ +From 52649b63ebd0dc45df0c5e6b209af6f6d96515ca Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +Date: Thu, 2 Jan 2020 14:45:28 +0100 +Subject: [PATCH] Check for overflow when allocating two-dimensional arrays + +Found by lgtm.com +--- + xmlregexp.c | 46 +++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 37 insertions(+), 9 deletions(-) + +diff --git a/xmlregexp.c b/xmlregexp.c +index 5a2deb9..0bd938f 100644 +--- a/xmlregexp.c ++++ b/xmlregexp.c +@@ -26,6 +26,9 @@ + #ifdef HAVE_LIMITS_H + #include + #endif ++#ifdef HAVE_STDINT_H ++#include ++#endif + + #include + #include +@@ -36,6 +39,9 @@ + #ifndef INT_MAX + #define INT_MAX 123456789 /* easy to flag and big enough for our needs */ + #endif ++#ifndef SIZE_MAX ++#define SIZE_MAX ((size_t) -1) ++#endif + + /* #define DEBUG_REGEXP_GRAPH */ + /* #define DEBUG_REGEXP_EXEC */ +@@ -418,6 +424,32 @@ xmlRegexpErrCompile(xmlRegParserCtxtPtr ctxt, const char *extra) + ************************************************************************/ + + static int xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt); ++ ++/** ++ * xmlRegCalloc2: ++ * @dim1: size of first dimension ++ * @dim2: size of second dimension ++ * @elemSize: size of element ++ * ++ * Allocate a two-dimensional array and set all elements to zero. ++ * ++ * Returns the new array or NULL in case of error. ++ */ ++static void* ++xmlRegCalloc2(size_t dim1, size_t dim2, size_t elemSize) { ++ size_t totalSize; ++ void *ret; ++ ++ /* Check for overflow */ ++ if (dim1 > SIZE_MAX / dim2 / elemSize) ++ return (NULL); ++ totalSize = dim1 * dim2 * elemSize; ++ ret = xmlMalloc(totalSize); ++ if (ret != NULL) ++ memset(ret, 0, totalSize); ++ return (ret); ++} ++ + /** + * xmlRegEpxFromParse: + * @ctxt: the parser context used to build it +@@ -540,8 +572,8 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) { + #ifdef DEBUG_COMPACTION + printf("Final: %d atoms\n", nbatoms); + #endif +- transitions = (int *) xmlMalloc((nbstates + 1) * +- (nbatoms + 1) * sizeof(int)); ++ transitions = (int *) xmlRegCalloc2(nbstates + 1, nbatoms + 1, ++ sizeof(int)); + if (transitions == NULL) { + xmlFree(stateRemap); + xmlFree(stringRemap); +@@ -551,7 +583,6 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) { + xmlFree(ret); + return(NULL); + } +- memset(transitions, 0, (nbstates + 1) * (nbatoms + 1) * sizeof(int)); + + /* + * Allocate the transition table. The first entry for each +@@ -577,12 +608,9 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) { + continue; + atomno = stringRemap[trans->atom->no]; + if ((trans->atom->data != NULL) && (transdata == NULL)) { +- transdata = (void **) xmlMalloc(nbstates * nbatoms * +- sizeof(void *)); +- if (transdata != NULL) +- memset(transdata, 0, +- nbstates * nbatoms * sizeof(void *)); +- else { ++ transdata = (void **) xmlRegCalloc2(nbstates, nbatoms, ++ sizeof(void *)); ++ if (transdata == NULL) { + xmlRegexpErrMemory(ctxt, "compiling regexp"); + break; + } +-- +1.8.3.1 + diff --git a/Copy-some-XMLReader-option-flags-to-parser-context.patch b/Copy-some-XMLReader-option-flags-to-parser-context.patch new file mode 100644 index 0000000000000000000000000000000000000000..20ff0ea1d36c17bbcf76fb44b3aacc12c79e5db6 --- /dev/null +++ b/Copy-some-XMLReader-option-flags-to-parser-context.patch @@ -0,0 +1,41 @@ +From 5c7e0a9a4608ac442e727f6e479cf2a6dea368ec Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +Date: Tue, 11 Feb 2020 16:29:30 +0100 +Subject: [PATCH] Copy some XMLReader option flags to parser context + +The parser context stores some options both in the "options" bits and +extra members like "validate" or "replaceEntities". Which of these +are actually read is inconsistent, so make sure to also update the +bit field. +--- + xmlreader.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/xmlreader.c b/xmlreader.c +index f3891e4..e336bc7 100644 +--- a/xmlreader.c ++++ b/xmlreader.c +@@ -3848,16 +3848,20 @@ xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) { + return(0); + case XML_PARSER_VALIDATE: + if (value != 0) { ++ ctxt->options |= XML_PARSE_DTDVALID; + ctxt->validate = 1; + reader->validate = XML_TEXTREADER_VALIDATE_DTD; + } else { ++ ctxt->options &= ~XML_PARSE_DTDVALID; + ctxt->validate = 0; + } + return(0); + case XML_PARSER_SUBST_ENTITIES: + if (value != 0) { ++ ctxt->options |= XML_PARSE_NOENT; + ctxt->replaceEntities = 1; + } else { ++ ctxt->options &= ~XML_PARSE_NOENT; + ctxt->replaceEntities = 0; + } + return(0); +-- +1.8.3.1 + diff --git a/Don-t-load-external-entity-from-xmlSAX2GetEntity.patch b/Don-t-load-external-entity-from-xmlSAX2GetEntity.patch new file mode 100644 index 0000000000000000000000000000000000000000..c74091c3de981eab3618fc89b9467693c7b584d1 --- /dev/null +++ b/Don-t-load-external-entity-from-xmlSAX2GetEntity.patch @@ -0,0 +1,99 @@ +From eddfbc38fa7e84ccd480eab3738e40d1b2c83979 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +Date: Wed, 22 Jan 2020 22:03:45 +0100 +Subject: [PATCH] Don't load external entity from xmlSAX2GetEntity + +Despite the comment, I can't see a reason why external entities must be +loaded in the SAX handler. For external entities, the handler is +typically first invoked via xmlParseReference which will later load the +entity on its own if it wasn't loaded yet. + +The old code also lead to duplicated SAX events which makes it +basically impossible to reuse xmlSAX2GetEntity for a custom SAX parser. +See the change to the expected test output. + +Note that xmlSAX2GetEntity was loading the entity via +xmlParseCtxtExternalEntity while xmlParseReference uses +xmlParseExternalEntityPrivate. In the previous commit, the two +functions were merged, trying to compensate for some slight differences +between the two mostly identical implementations. + +But the more urgent reason for this change is that xmlParseReference +has the facility to abort early when recursive entities are detected, +avoiding what could practically amount to an infinite loop. + +If you want to backport this change, note that the previous three +commits are required as well: + +f9ea1a24 Fix copying of entities in xmlParseReference +5c7e0a9a Copy some XMLReader option flags to parser context +1a3e584a Merge code paths loading external entities + +Found by OSS-Fuzz. +--- + SAX2.c | 30 ------------------------------ + result/noent/ent2.sax2 | 7 ------- + 2 files changed, 37 deletions(-) + +diff --git a/SAX2.c b/SAX2.c +index 5f141f9..6045ca1 100644 +--- a/SAX2.c ++++ b/SAX2.c +@@ -590,36 +590,6 @@ xmlSAX2GetEntity(void *ctx, const xmlChar *name) + } else { + ret = xmlGetDocEntity(ctxt->myDoc, name); + } +- if ((ret != NULL) && +- ((ctxt->validate) || (ctxt->replaceEntities)) && +- (ret->children == NULL) && +- (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) { +- int val; +- +- /* +- * for validation purposes we really need to fetch and +- * parse the external entity +- */ +- xmlNodePtr children; +- unsigned long oldnbent = ctxt->nbentities; +- +- val = xmlParseCtxtExternalEntity(ctxt, ret->URI, +- ret->ExternalID, &children); +- if (val == 0) { +- xmlAddChildList((xmlNodePtr) ret, children); +- } else { +- xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING, +- "Failure to process entity %s\n", name, NULL); +- ctxt->validate = 0; +- return(NULL); +- } +- ret->owner = 1; +- if (ret->checked == 0) { +- ret->checked = (ctxt->nbentities - oldnbent + 1) * 2; +- if ((ret->content != NULL) && (xmlStrchr(ret->content, '<'))) +- ret->checked |= 1; +- } +- } + return(ret); + } + +diff --git a/result/noent/ent2.sax2 b/result/noent/ent2.sax2 +index 88c6aa6..d17f2ff 100644 +--- a/result/noent/ent2.sax2 ++++ b/result/noent/ent2.sax2 +@@ -17,13 +17,6 @@ SAX.characters(my title, 8) + SAX.endElementNs(title, NULL, NULL) + SAX.characters( + , 1) +-SAX.ignorableWhitespace( +-, 1) +-SAX.startElementNs(title, NULL, NULL, 0, 0, 0) +-SAX.characters(my title, 8) +-SAX.endElementNs(title, NULL, NULL) +-SAX.characters( +-, 1) + SAX.characters( + This text is about XML, the, 31) + SAX.getEntity(xml) +-- +1.8.3.1 + diff --git a/Fix-copying-of-entities-in-xmlParseReference.patch b/Fix-copying-of-entities-in-xmlParseReference.patch new file mode 100644 index 0000000000000000000000000000000000000000..a100a7619be6f58c33ecbb43ad0c9fdbc46e4341 --- /dev/null +++ b/Fix-copying-of-entities-in-xmlParseReference.patch @@ -0,0 +1,135 @@ +From f9ea1a24ed0fd2fd051bb01b0d08cdff60887938 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +Date: Tue, 11 Feb 2020 16:17:34 +0100 +Subject: [PATCH] Fix copying of entities in xmlParseReference + +Before, reader mode would end up in a branch that didn't handle +entities with multiple children and failed to update ent->last, so the +hack copying the "extra" reader data wouldn't trigger. Consequently, +some empty nodes in entities are correctly detected now in the test +suite. (The detection of empty nodes in entities is still buggy, +though.) +--- + parser.c | 64 +++++++++++++++++++++++++++------------------------------ + result/att7.rde | 3 +-- + result/ent9.rde | 6 ++---- + 3 files changed, 33 insertions(+), 40 deletions(-) + +diff --git a/parser.c b/parser.c +index 1ba988c..5ff8592 100644 +--- a/parser.c ++++ b/parser.c +@@ -7159,42 +7159,38 @@ xmlParseReference(xmlParserCtxtPtr ctxt) { + (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY))&& + (ent->children == NULL)) { + ent->children = list; +- if (ctxt->replaceEntities) { +- /* +- * Prune it directly in the generated document +- * except for single text nodes. +- */ +- if (((list->type == XML_TEXT_NODE) && +- (list->next == NULL)) || +- (ctxt->parseMode == XML_PARSE_READER)) { +- list->parent = (xmlNodePtr) ent; +- list = NULL; +- ent->owner = 1; +- } else { +- ent->owner = 0; +- while (list != NULL) { +- list->parent = (xmlNodePtr) ctxt->node; +- list->doc = ctxt->myDoc; +- if (list->next == NULL) +- ent->last = list; +- list = list->next; +- } +- list = ent->children; ++ /* ++ * Prune it directly in the generated document ++ * except for single text nodes. ++ */ ++ if ((ctxt->replaceEntities == 0) || ++ (ctxt->parseMode == XML_PARSE_READER) || ++ ((list->type == XML_TEXT_NODE) && ++ (list->next == NULL))) { ++ ent->owner = 1; ++ while (list != NULL) { ++ list->parent = (xmlNodePtr) ent; ++ xmlSetTreeDoc(list, ent->doc); ++ if (list->next == NULL) ++ ent->last = list; ++ list = list->next; ++ } ++ list = NULL; ++ } else { ++ ent->owner = 0; ++ while (list != NULL) { ++ list->parent = (xmlNodePtr) ctxt->node; ++ list->doc = ctxt->myDoc; ++ if (list->next == NULL) ++ ent->last = list; ++ list = list->next; ++ } ++ list = ent->children; + #ifdef LIBXML_LEGACY_ENABLED +- if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) +- xmlAddEntityReference(ent, list, NULL); ++ if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) ++ xmlAddEntityReference(ent, list, NULL); + #endif /* LIBXML_LEGACY_ENABLED */ +- } +- } else { +- ent->owner = 1; +- while (list != NULL) { +- list->parent = (xmlNodePtr) ent; +- xmlSetTreeDoc(list, ent->doc); +- if (list->next == NULL) +- ent->last = list; +- list = list->next; +- } +- } ++ } + } else { + xmlFreeNodeList(list); + list = NULL; +diff --git a/result/att7.rde b/result/att7.rde +index afcef5f..6079637 100644 +--- a/result/att7.rde ++++ b/result/att7.rde +@@ -5,8 +5,7 @@ + 1 1 test 1 0 + 1 14 #text 0 1 + +-1 1 test 0 0 +-1 15 test 0 0 ++1 1 test 1 0 + 1 14 #text 0 1 + + 0 15 x 0 0 +diff --git a/result/ent9.rde b/result/ent9.rde +index 38b9f43..2206146 100644 +--- a/result/ent9.rde ++++ b/result/ent9.rde +@@ -12,8 +12,7 @@ + 2 1 c 0 0 + 2 15 c 0 0 + 2 3 #text 0 1 , +-2 1 d 0 0 +-2 15 d 0 0 ++2 1 d 1 0 + 1 15 ent 0 0 + 1 14 #text 0 1 + +@@ -292,8 +291,7 @@ + 2 1 c 0 0 + 2 15 c 0 0 + 2 3 #text 0 1 , +-2 1 d 0 0 +-2 15 d 0 0 ++2 1 d 1 0 + 1 15 ent 0 0 + 1 14 #text 0 1 + +-- +1.8.3.1 + diff --git a/Fix-freeing-of-nested-documents.patch b/Fix-freeing-of-nested-documents.patch new file mode 100644 index 0000000000000000000000000000000000000000..cdbd51b142eccee1eca159960813ee2d4651ec77 --- /dev/null +++ b/Fix-freeing-of-nested-documents.patch @@ -0,0 +1,33 @@ +From 0815302dee2b78139832c2080348086a0564836b Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +Date: Fri, 6 Dec 2019 12:27:29 +0100 +Subject: [PATCH] Fix freeing of nested documents + +Apparently, some libxslt RVTs can contain nested document nodes, see +issue #132. I'm not sure how this happens exactly but it can cause a +segfault in xmlFreeNodeList after the changes in commit 0762c9b6. + +Make sure not to touch the (nonexistent) `content` member of xmlDocs. +--- + tree.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/tree.c b/tree.c +index 070670f..0d7fc98 100644 +--- a/tree.c ++++ b/tree.c +@@ -3708,6 +3708,11 @@ xmlFreeNodeList(xmlNodePtr cur) { + (cur->type != XML_XINCLUDE_START) && + (cur->type != XML_XINCLUDE_END) && + (cur->type != XML_ENTITY_REF_NODE) && ++ (cur->type != XML_DOCUMENT_NODE) && ++#ifdef LIBXML_DOCB_ENABLED ++ (cur->type != XML_DOCB_DOCUMENT_NODE) && ++#endif ++ (cur->type != XML_HTML_DOCUMENT_NODE) && + (cur->content != (xmlChar *) &(cur->properties))) { + DICT_FREE(cur->content) + } +-- +1.8.3.1 + diff --git a/Fix-integer-overflow-in-xmlBufferResize.patch b/Fix-integer-overflow-in-xmlBufferResize.patch new file mode 100644 index 0000000000000000000000000000000000000000..dc2bc2007779e940fb47b8538e7495885d95f9b4 --- /dev/null +++ b/Fix-integer-overflow-in-xmlBufferResize.patch @@ -0,0 +1,45 @@ +From b07251215ef48c70c6e56f7351406c47cfca4d5b Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +Date: Fri, 10 Jan 2020 15:55:07 +0100 +Subject: [PATCH] Fix integer overflow in xmlBufferResize + +Found by OSS-Fuzz. +--- + tree.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/tree.c b/tree.c +index 0d7fc98..f43f6de 100644 +--- a/tree.c ++++ b/tree.c +@@ -7424,12 +7424,17 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size) + if (size < buf->size) + return 1; + ++ if (size > UINT_MAX - 10) { ++ xmlTreeErrMemory("growing buffer"); ++ return 0; ++ } ++ + /* figure out new size */ + switch (buf->alloc){ + case XML_BUFFER_ALLOC_IO: + case XML_BUFFER_ALLOC_DOUBLEIT: + /*take care of empty case*/ +- newSize = (buf->size ? buf->size*2 : size + 10); ++ newSize = (buf->size ? buf->size : size + 10); + while (size > newSize) { + if (newSize > UINT_MAX / 2) { + xmlTreeErrMemory("growing buffer"); +@@ -7445,7 +7450,7 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size) + if (buf->use < BASE_BUFFER_SIZE) + newSize = size; + else { +- newSize = buf->size * 2; ++ newSize = buf->size; + while (size > newSize) { + if (newSize > UINT_MAX / 2) { + xmlTreeErrMemory("growing buffer"); +-- +1.8.3.1 + diff --git a/Fix-memory-leak-in-error-path-of-XPath-expr-parser.patch b/Fix-memory-leak-in-error-path-of-XPath-expr-parser.patch new file mode 100644 index 0000000000000000000000000000000000000000..9593e042cfd984c1b2f4488a046438f189750770 --- /dev/null +++ b/Fix-memory-leak-in-error-path-of-XPath-expr-parser.patch @@ -0,0 +1,67 @@ +From d5f2f74d0f0e7906eabb32c57e09a13ac3e578a2 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +Date: Mon, 11 Nov 2019 11:27:40 +0100 +Subject: [PATCH] Fix memory leak in error path of XPath expr parser + +Also propagate memory errors. + +Found by OSS-Fuzz. +--- + xpath.c | 20 ++++++++++++++++---- + 1 file changed, 16 insertions(+), 4 deletions(-) + +diff --git a/xpath.c b/xpath.c +index 9f64ab9..ff1137f 100644 +--- a/xpath.c ++++ b/xpath.c +@@ -10088,6 +10088,7 @@ xmlXPathCompNumber(xmlXPathParserContextPtr ctxt) + int ok = 0; + int exponent = 0; + int is_exponent_negative = 0; ++ xmlXPathObjectPtr num; + #ifdef __GNUC__ + unsigned long tmp = 0; + double temp; +@@ -10160,8 +10161,13 @@ xmlXPathCompNumber(xmlXPathParserContextPtr ctxt) + exponent = -exponent; + ret *= pow(10.0, (double) exponent); + } +- PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_NUMBER, 0, 0, +- xmlXPathCacheNewFloat(ctxt->context, ret), NULL); ++ num = xmlXPathCacheNewFloat(ctxt->context, ret); ++ if (num == NULL) { ++ ctxt->error = XPATH_MEMORY_ERROR; ++ } else if (PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_NUMBER, 0, 0, num, ++ NULL) == -1) { ++ xmlXPathReleaseObject(ctxt->context, num); ++ } + } + + /** +@@ -10223,6 +10229,7 @@ static void + xmlXPathCompLiteral(xmlXPathParserContextPtr ctxt) { + const xmlChar *q; + xmlChar *ret = NULL; ++ xmlXPathObjectPtr lit; + + if (CUR == '"') { + NEXT; +@@ -10250,8 +10257,13 @@ xmlXPathCompLiteral(xmlXPathParserContextPtr ctxt) { + XP_ERROR(XPATH_START_LITERAL_ERROR); + } + if (ret == NULL) return; +- PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_STRING, 0, 0, +- xmlXPathCacheNewString(ctxt->context, ret), NULL); ++ lit = xmlXPathCacheNewString(ctxt->context, ret); ++ if (lit == NULL) { ++ ctxt->error = XPATH_MEMORY_ERROR; ++ } else if (PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_STRING, 0, 0, lit, ++ NULL) == -1) { ++ xmlXPathReleaseObject(ctxt->context, lit); ++ } + xmlFree(ret); + } + +-- +1.8.3.1 + diff --git a/Fix-memory-leaks-of-encoding-handlers-in-xmlsave-c.patch b/Fix-memory-leaks-of-encoding-handlers-in-xmlsave-c.patch new file mode 100644 index 0000000000000000000000000000000000000000..0feef5092933e39e25f773731fc3c04d275dc4da --- /dev/null +++ b/Fix-memory-leaks-of-encoding-handlers-in-xmlsave-c.patch @@ -0,0 +1,79 @@ +From 42942066e1f6422e26cd162a6014b19ac215083f Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +Date: Mon, 11 Nov 2019 13:49:11 +0100 +Subject: [PATCH] Fix memory leaks of encoding handlers in xmlsave.c + +Fix leak of iconv/ICU encoding handler in xmlSaveToBuffer. + +Fix leaks of iconv/ICU encoding handlers in xmlSaveTo* error paths. + +Closes #127. +--- + xmlsave.c | 26 ++++++++------------------ + 1 file changed, 8 insertions(+), 18 deletions(-) + +diff --git a/xmlsave.c b/xmlsave.c +index fa00915..7158c26 100644 +--- a/xmlsave.c ++++ b/xmlsave.c +@@ -1802,6 +1802,7 @@ xmlSaveToFd(int fd, const char *encoding, int options) + if (ret == NULL) return(NULL); + ret->buf = xmlOutputBufferCreateFd(fd, ret->handler); + if (ret->buf == NULL) { ++ xmlCharEncCloseFunc(ret->handler); + xmlFreeSaveCtxt(ret); + return(NULL); + } +@@ -1831,6 +1832,7 @@ xmlSaveToFilename(const char *filename, const char *encoding, int options) + ret->buf = xmlOutputBufferCreateFilename(filename, ret->handler, + compression); + if (ret->buf == NULL) { ++ xmlCharEncCloseFunc(ret->handler); + xmlFreeSaveCtxt(ret); + return(NULL); + } +@@ -1853,28 +1855,15 @@ xmlSaveCtxtPtr + xmlSaveToBuffer(xmlBufferPtr buffer, const char *encoding, int options) + { + xmlSaveCtxtPtr ret; +- xmlOutputBufferPtr out_buff; +- xmlCharEncodingHandlerPtr handler; + + ret = xmlNewSaveCtxt(encoding, options); + if (ret == NULL) return(NULL); +- +- if (encoding != NULL) { +- handler = xmlFindCharEncodingHandler(encoding); +- if (handler == NULL) { +- xmlFree(ret); +- return(NULL); +- } +- } else +- handler = NULL; +- out_buff = xmlOutputBufferCreateBuffer(buffer, handler); +- if (out_buff == NULL) { +- xmlFree(ret); +- if (handler) xmlCharEncCloseFunc(handler); +- return(NULL); ++ ret->buf = xmlOutputBufferCreateBuffer(buffer, ret->handler); ++ if (ret->buf == NULL) { ++ xmlCharEncCloseFunc(ret->handler); ++ xmlFreeSaveCtxt(ret); ++ return(NULL); + } +- +- ret->buf = out_buff; + return(ret); + } + +@@ -1902,6 +1891,7 @@ xmlSaveToIO(xmlOutputWriteCallback iowrite, + if (ret == NULL) return(NULL); + ret->buf = xmlOutputBufferCreateIO(iowrite, ioclose, ioctx, ret->handler); + if (ret->buf == NULL) { ++ xmlCharEncCloseFunc(ret->handler); + xmlFreeSaveCtxt(ret); + return(NULL); + } +-- +1.8.3.1 + diff --git a/Fix-more-memory-leaks-in-error-paths-of-XPath-parser.patch b/Fix-more-memory-leaks-in-error-paths-of-XPath-parser.patch new file mode 100644 index 0000000000000000000000000000000000000000..fc67fcedb533f71d2687f615b43623facdc9619a --- /dev/null +++ b/Fix-more-memory-leaks-in-error-paths-of-XPath-parser.patch @@ -0,0 +1,76 @@ +From 2c80fc911678adc9dcf252b3bc71cce101c8728e Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +Date: Mon, 2 Dec 2019 11:30:30 +0100 +Subject: [PATCH] Fix more memory leaks in error paths of XPath parser + +Found by OSS-Fuzz. +--- + xpath.c | 24 +++++++++++++++--------- + 1 file changed, 15 insertions(+), 9 deletions(-) + +diff --git a/xpath.c b/xpath.c +index ff1137f..030bab3 100644 +--- a/xpath.c ++++ b/xpath.c +@@ -10300,8 +10300,10 @@ xmlXPathCompVariableReference(xmlXPathParserContextPtr ctxt) { + XP_ERROR(XPATH_VARIABLE_REF_ERROR); + } + ctxt->comp->last = -1; +- PUSH_LONG_EXPR(XPATH_OP_VARIABLE, 0, 0, 0, +- name, prefix); ++ if (PUSH_LONG_EXPR(XPATH_OP_VARIABLE, 0, 0, 0, name, prefix) == -1) { ++ xmlFree(prefix); ++ xmlFree(name); ++ } + SKIP_BLANKS; + if ((ctxt->context != NULL) && (ctxt->context->flags & XML_XPATH_NOVAR)) { + XP_ERROR(XPATH_FORBID_VARIABLE_ERROR); +@@ -10408,8 +10410,10 @@ xmlXPathCompFunctionCall(xmlXPathParserContextPtr ctxt) { + SKIP_BLANKS; + } + } +- PUSH_LONG_EXPR(XPATH_OP_FUNCTION, nbargs, 0, 0, +- name, prefix); ++ if (PUSH_LONG_EXPR(XPATH_OP_FUNCTION, nbargs, 0, 0, name, prefix) == -1) { ++ xmlFree(prefix); ++ xmlFree(name); ++ } + NEXT; + SKIP_BLANKS; + } +@@ -11050,7 +11054,7 @@ xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter) { + */ + static xmlChar * + xmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt, xmlXPathTestVal *test, +- xmlXPathTypeVal *type, const xmlChar **prefix, ++ xmlXPathTypeVal *type, xmlChar **prefix, + xmlChar *name) { + int blanks; + +@@ -11281,7 +11285,7 @@ xmlXPathCompStep(xmlXPathParserContextPtr ctxt) { + SKIP_BLANKS; + } else { + xmlChar *name = NULL; +- const xmlChar *prefix = NULL; ++ xmlChar *prefix = NULL; + xmlXPathTestVal test = (xmlXPathTestVal) 0; + xmlXPathAxisVal axis = (xmlXPathAxisVal) 0; + xmlXPathTypeVal type = (xmlXPathTypeVal) 0; +@@ -11391,9 +11395,11 @@ eval_predicates: + PUSH_BINARY_EXPR(XPATH_OP_RANGETO, op2, op1, 0, 0); + } else + #endif +- PUSH_FULL_EXPR(XPATH_OP_COLLECT, op1, ctxt->comp->last, axis, +- test, type, (void *)prefix, (void *)name); +- ++ if (PUSH_FULL_EXPR(XPATH_OP_COLLECT, op1, ctxt->comp->last, axis, ++ test, type, (void *)prefix, (void *)name) == -1) { ++ xmlFree(prefix); ++ xmlFree(name); ++ } + } + #ifdef DEBUG_STEP + xmlGenericError(xmlGenericErrorContext, "Step : "); +-- +1.8.3.1 + diff --git a/Fix-overflow-check-in-xmlNodeDump.patch b/Fix-overflow-check-in-xmlNodeDump.patch new file mode 100644 index 0000000000000000000000000000000000000000..e8004e225acbb2e887664a9b3fe1b2b57267edfe --- /dev/null +++ b/Fix-overflow-check-in-xmlNodeDump.patch @@ -0,0 +1,29 @@ +From c9faa29259ac23b5fbf945f61056288e413dae81 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +Date: Thu, 2 Jan 2020 14:12:39 +0100 +Subject: [PATCH] Fix overflow check in xmlNodeDump + +Store return value of xmlBufNodeDump in a size_t before checking for +integer overflow. + +Found by lgtm.com +--- + xmlsave.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xmlsave.c b/xmlsave.c +index 7158c26..b06e24d 100644 +--- a/xmlsave.c ++++ b/xmlsave.c +@@ -2187,7 +2187,7 @@ xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level, + int format) + { + xmlBufPtr buffer; +- int ret; ++ size_t ret; + + if ((buf == NULL) || (cur == NULL)) + return(-1); +-- +1.8.3.1 + diff --git a/Fix-overflow-handling-in-xmlBufBackToBuffer.patch b/Fix-overflow-handling-in-xmlBufBackToBuffer.patch new file mode 100644 index 0000000000000000000000000000000000000000..75e0288a28b014f0ef261f5b4fb32bb1ff344c6f --- /dev/null +++ b/Fix-overflow-handling-in-xmlBufBackToBuffer.patch @@ -0,0 +1,34 @@ +From bf2e96173d4f78f564015a925970077501586fbe Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +Date: Thu, 7 Nov 2019 12:54:01 +0100 +Subject: [PATCH] Fix overflow handling in xmlBufBackToBuffer + +Don't overwrite 'use' and 'size' members after clamping to INT_MAX. + +Thanks to Ranier Vilela for pointing this out in merge request !56. +--- + buf.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/buf.c b/buf.c +index d46da36..3b212fc 100644 +--- a/buf.c ++++ b/buf.c +@@ -1233,10 +1233,12 @@ xmlBufBackToBuffer(xmlBufPtr buf) { + * Keep the buffer but provide a truncated size value. + */ + xmlBufOverflowError(buf, "Allocated size too big for xmlBuffer"); ++ ret->use = (int) buf->use; + ret->size = INT_MAX; ++ } else { ++ ret->use = (int) buf->use; ++ ret->size = (int) buf->size; + } +- ret->use = (int) buf->use; +- ret->size = (int) buf->size; + ret->alloc = buf->alloc; + ret->content = buf->content; + ret->contentIO = buf->contentIO; +-- +1.8.3.1 + diff --git a/Merge-code-paths-loading-external-entities.patch b/Merge-code-paths-loading-external-entities.patch new file mode 100644 index 0000000000000000000000000000000000000000..ef5822ece136674582dfb201680d81ae53e1d2d3 --- /dev/null +++ b/Merge-code-paths-loading-external-entities.patch @@ -0,0 +1,361 @@ +From 1a3e584a5af0f6ffc6f80a3caa192eb8c0389611 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +Date: Tue, 21 Jan 2020 22:12:42 +0100 +Subject: [PATCH] Merge code paths loading external entities + +Merge xmlParseCtxtExternalEntity into xmlParseExternalEntityPrivate. +--- + parser.c | 282 ++++++++++++++++----------------------------------------------- + 1 file changed, 72 insertions(+), 210 deletions(-) + +diff --git a/parser.c b/parser.c +index 5ff8592..0ca58e8 100644 +--- a/parser.c ++++ b/parser.c +@@ -12891,189 +12891,21 @@ xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) { + int + xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL, + const xmlChar *ID, xmlNodePtr *lst) { +- xmlParserCtxtPtr ctxt; +- xmlDocPtr newDoc; +- xmlNodePtr newRoot; +- xmlSAXHandlerPtr oldsax = NULL; +- int ret = 0; +- xmlChar start[4]; +- xmlCharEncoding enc; ++ void *userData; + + if (ctx == NULL) return(-1); +- +- if (((ctx->depth > 40) && ((ctx->options & XML_PARSE_HUGE) == 0)) || +- (ctx->depth > 1024)) { +- return(XML_ERR_ENTITY_LOOP); +- } +- +- if (lst != NULL) +- *lst = NULL; +- if ((URL == NULL) && (ID == NULL)) +- return(-1); +- if (ctx->myDoc == NULL) /* @@ relax but check for dereferences */ +- return(-1); +- +- ctxt = xmlCreateEntityParserCtxtInternal(URL, ID, NULL, ctx); +- if (ctxt == NULL) { +- return(-1); +- } +- +- oldsax = ctxt->sax; +- ctxt->sax = ctx->sax; +- xmlDetectSAX2(ctxt); +- newDoc = xmlNewDoc(BAD_CAST "1.0"); +- if (newDoc == NULL) { +- xmlFreeParserCtxt(ctxt); +- return(-1); +- } +- newDoc->properties = XML_DOC_INTERNAL; +- if (ctx->myDoc->dict) { +- newDoc->dict = ctx->myDoc->dict; +- xmlDictReference(newDoc->dict); +- } +- if (ctx->myDoc != NULL) { +- newDoc->intSubset = ctx->myDoc->intSubset; +- newDoc->extSubset = ctx->myDoc->extSubset; +- } +- if (ctx->myDoc->URL != NULL) { +- newDoc->URL = xmlStrdup(ctx->myDoc->URL); +- } +- newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL); +- if (newRoot == NULL) { +- ctxt->sax = oldsax; +- xmlFreeParserCtxt(ctxt); +- newDoc->intSubset = NULL; +- newDoc->extSubset = NULL; +- xmlFreeDoc(newDoc); +- return(-1); +- } +- xmlAddChild((xmlNodePtr) newDoc, newRoot); +- nodePush(ctxt, newDoc->children); +- if (ctx->myDoc == NULL) { +- ctxt->myDoc = newDoc; +- } else { +- ctxt->myDoc = ctx->myDoc; +- newDoc->children->doc = ctx->myDoc; +- } +- + /* +- * Get the 4 first bytes and decode the charset +- * if enc != XML_CHAR_ENCODING_NONE +- * plug some encoding conversion routines. +- */ +- GROW +- if ((ctxt->input->end - ctxt->input->cur) >= 4) { +- start[0] = RAW; +- start[1] = NXT(1); +- start[2] = NXT(2); +- start[3] = NXT(3); +- enc = xmlDetectCharEncoding(start, 4); +- if (enc != XML_CHAR_ENCODING_NONE) { +- xmlSwitchEncoding(ctxt, enc); +- } +- } +- +- /* +- * Parse a possible text declaration first +- */ +- if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) { +- xmlParseTextDecl(ctxt); +- /* +- * An XML-1.0 document can't reference an entity not XML-1.0 +- */ +- if ((xmlStrEqual(ctx->version, BAD_CAST "1.0")) && +- (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) { +- xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH, +- "Version mismatch between document and entity\n"); +- } +- } +- +- /* +- * If the user provided its own SAX callbacks then reuse the +- * useData callback field, otherwise the expected setup in a ++ * If the user provided their own SAX callbacks, then reuse the ++ * userData callback field, otherwise the expected setup in a + * DOM builder is to have userData == ctxt + */ + if (ctx->userData == ctx) +- ctxt->userData = ctxt; ++ userData = NULL; + else +- ctxt->userData = ctx->userData; +- +- /* +- * Doing validity checking on chunk doesn't make sense +- */ +- ctxt->instate = XML_PARSER_CONTENT; +- ctxt->validate = ctx->validate; +- ctxt->valid = ctx->valid; +- ctxt->loadsubset = ctx->loadsubset; +- ctxt->depth = ctx->depth + 1; +- ctxt->replaceEntities = ctx->replaceEntities; +- if (ctxt->validate) { +- ctxt->vctxt.error = ctx->vctxt.error; +- ctxt->vctxt.warning = ctx->vctxt.warning; +- } else { +- ctxt->vctxt.error = NULL; +- ctxt->vctxt.warning = NULL; +- } +- ctxt->vctxt.nodeTab = NULL; +- ctxt->vctxt.nodeNr = 0; +- ctxt->vctxt.nodeMax = 0; +- ctxt->vctxt.node = NULL; +- if (ctxt->dict != NULL) xmlDictFree(ctxt->dict); +- ctxt->dict = ctx->dict; +- ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3); +- ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5); +- ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36); +- ctxt->dictNames = ctx->dictNames; +- ctxt->attsDefault = ctx->attsDefault; +- ctxt->attsSpecial = ctx->attsSpecial; +- ctxt->linenumbers = ctx->linenumbers; +- +- xmlParseContent(ctxt); +- +- ctx->validate = ctxt->validate; +- ctx->valid = ctxt->valid; +- if ((RAW == '<') && (NXT(1) == '/')) { +- xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); +- } else if (RAW != 0) { +- xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL); +- } +- if (ctxt->node != newDoc->children) { +- xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); +- } +- +- if (!ctxt->wellFormed) { +- if (ctxt->errNo == 0) +- ret = 1; +- else +- ret = ctxt->errNo; +- } else { +- if (lst != NULL) { +- xmlNodePtr cur; +- +- /* +- * Return the newly created nodeset after unlinking it from +- * they pseudo parent. +- */ +- cur = newDoc->children->children; +- *lst = cur; +- while (cur != NULL) { +- cur->parent = NULL; +- cur = cur->next; +- } +- newDoc->children->children = NULL; +- } +- ret = 0; +- } +- ctxt->sax = oldsax; +- ctxt->dict = NULL; +- ctxt->attsDefault = NULL; +- ctxt->attsSpecial = NULL; +- xmlFreeParserCtxt(ctxt); +- newDoc->intSubset = NULL; +- newDoc->extSubset = NULL; +- xmlFreeDoc(newDoc); +- +- return(ret); ++ userData = ctx->userData; ++ return xmlParseExternalEntityPrivate(ctx->myDoc, ctx, ctx->sax, ++ userData, ctx->depth + 1, ++ URL, ID, lst); + } + + /** +@@ -13123,25 +12955,6 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, + ctxt = xmlCreateEntityParserCtxtInternal(URL, ID, NULL, oldctxt); + if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY); + ctxt->userData = ctxt; +- if (oldctxt != NULL) { +- ctxt->_private = oldctxt->_private; +- ctxt->loadsubset = oldctxt->loadsubset; +- ctxt->validate = oldctxt->validate; +- ctxt->external = oldctxt->external; +- ctxt->record_info = oldctxt->record_info; +- ctxt->node_seq.maximum = oldctxt->node_seq.maximum; +- ctxt->node_seq.length = oldctxt->node_seq.length; +- ctxt->node_seq.buffer = oldctxt->node_seq.buffer; +- } else { +- /* +- * Doing validity checking on chunk without context +- * doesn't make sense +- */ +- ctxt->_private = NULL; +- ctxt->validate = 0; +- ctxt->external = 2; +- ctxt->loadsubset = 0; +- } + if (sax != NULL) { + oldsax = ctxt->sax; + ctxt->sax = sax; +@@ -13151,28 +12964,25 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, + xmlDetectSAX2(ctxt); + newDoc = xmlNewDoc(BAD_CAST "1.0"); + if (newDoc == NULL) { +- ctxt->node_seq.maximum = 0; +- ctxt->node_seq.length = 0; +- ctxt->node_seq.buffer = NULL; + xmlFreeParserCtxt(ctxt); + return(XML_ERR_INTERNAL_ERROR); + } + newDoc->properties = XML_DOC_INTERNAL; +- newDoc->intSubset = doc->intSubset; +- newDoc->extSubset = doc->extSubset; +- newDoc->dict = doc->dict; +- xmlDictReference(newDoc->dict); +- +- if (doc->URL != NULL) { +- newDoc->URL = xmlStrdup(doc->URL); ++ if (doc) { ++ newDoc->intSubset = doc->intSubset; ++ newDoc->extSubset = doc->extSubset; ++ if (doc->dict) { ++ newDoc->dict = doc->dict; ++ xmlDictReference(newDoc->dict); ++ } ++ if (doc->URL != NULL) { ++ newDoc->URL = xmlStrdup(doc->URL); ++ } + } + newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL); + if (newRoot == NULL) { + if (sax != NULL) + ctxt->sax = oldsax; +- ctxt->node_seq.maximum = 0; +- ctxt->node_seq.length = 0; +- ctxt->node_seq.buffer = NULL; + xmlFreeParserCtxt(ctxt); + newDoc->intSubset = NULL; + newDoc->extSubset = NULL; +@@ -13181,8 +12991,12 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, + } + xmlAddChild((xmlNodePtr) newDoc, newRoot); + nodePush(ctxt, newDoc->children); +- ctxt->myDoc = doc; +- newRoot->doc = doc; ++ if (doc == NULL) { ++ ctxt->myDoc = newDoc; ++ } else { ++ ctxt->myDoc = doc; ++ newRoot->doc = doc; ++ } + + /* + * Get the 4 first bytes and decode the charset +@@ -13206,10 +13020,53 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, + */ + if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) { + xmlParseTextDecl(ctxt); ++ /* ++ * An XML-1.0 document can't reference an entity not XML-1.0 ++ */ ++ if ((xmlStrEqual(oldctxt->version, BAD_CAST "1.0")) && ++ (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) { ++ xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH, ++ "Version mismatch between document and entity\n"); ++ } + } + + ctxt->instate = XML_PARSER_CONTENT; + ctxt->depth = depth; ++ if (oldctxt != NULL) { ++ ctxt->_private = oldctxt->_private; ++ ctxt->loadsubset = oldctxt->loadsubset; ++ ctxt->validate = oldctxt->validate; ++ ctxt->valid = oldctxt->valid; ++ ctxt->replaceEntities = oldctxt->replaceEntities; ++ if (oldctxt->validate) { ++ ctxt->vctxt.error = oldctxt->vctxt.error; ++ ctxt->vctxt.warning = oldctxt->vctxt.warning; ++ ctxt->vctxt.userData = oldctxt->vctxt.userData; ++ } ++ ctxt->external = oldctxt->external; ++ if (ctxt->dict) xmlDictFree(ctxt->dict); ++ ctxt->dict = oldctxt->dict; ++ ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3); ++ ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5); ++ ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36); ++ ctxt->dictNames = oldctxt->dictNames; ++ ctxt->attsDefault = oldctxt->attsDefault; ++ ctxt->attsSpecial = oldctxt->attsSpecial; ++ ctxt->linenumbers = oldctxt->linenumbers; ++ ctxt->record_info = oldctxt->record_info; ++ ctxt->node_seq.maximum = oldctxt->node_seq.maximum; ++ ctxt->node_seq.length = oldctxt->node_seq.length; ++ ctxt->node_seq.buffer = oldctxt->node_seq.buffer; ++ } else { ++ /* ++ * Doing validity checking on chunk without context ++ * doesn't make sense ++ */ ++ ctxt->_private = NULL; ++ ctxt->validate = 0; ++ ctxt->external = 2; ++ ctxt->loadsubset = 0; ++ } + + xmlParseContent(ctxt); + +@@ -13269,6 +13126,11 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, + if (sax != NULL) + ctxt->sax = oldsax; + if (oldctxt != NULL) { ++ ctxt->dict = NULL; ++ ctxt->attsDefault = NULL; ++ ctxt->attsSpecial = NULL; ++ oldctxt->validate = ctxt->validate; ++ oldctxt->valid = ctxt->valid; + oldctxt->node_seq.maximum = ctxt->node_seq.maximum; + oldctxt->node_seq.length = ctxt->node_seq.length; + oldctxt->node_seq.buffer = ctxt->node_seq.buffer; +-- +1.8.3.1 + diff --git a/Null-pointer-handling-in-catalog-c.patch b/Null-pointer-handling-in-catalog-c.patch new file mode 100644 index 0000000000000000000000000000000000000000..d0cae73f2a403526b8898ed785fdcbfdf111ed43 --- /dev/null +++ b/Null-pointer-handling-in-catalog-c.patch @@ -0,0 +1,77 @@ +From d724861536f3cfb82750176aa45e655634bbbbcc Mon Sep 17 00:00:00 2001 +From: raniervf +Date: Mon, 4 Nov 2019 23:19:28 -0300 +Subject: [PATCH] Null pointer handling in catalog.c + +Fix potential deferencing potential null pointers; +Small optimizations. + +Closes #123. +--- + catalog.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/catalog.c b/catalog.c +index 7328fd3..b471e8a 100644 +--- a/catalog.c ++++ b/catalog.c +@@ -924,7 +924,7 @@ xmlParseCatalogFile(const char *filename) { + xmlBufResetInput(buf->buffer, inputStream); + + inputPush(ctxt, inputStream); +- if ((ctxt->directory == NULL) && (directory == NULL)) ++ if (ctxt->directory == NULL) + directory = xmlParserGetDirectory(filename); + if ((ctxt->directory == NULL) && (directory != NULL)) + ctxt->directory = directory; +@@ -2069,8 +2069,7 @@ xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID, + ret = xmlCatalogXMLResolve(catal->children, pubID, sysID); + if (ret != NULL) { + break; +- } else if ((catal->children != NULL) && +- (catal->children->depth > MAX_CATAL_DEPTH)) { ++ } else if (catal->children->depth > MAX_CATAL_DEPTH) { + ret = NULL; + break; + } +@@ -2353,7 +2352,7 @@ xmlParseSGMLCatalog(xmlCatalogPtr catal, const xmlChar *value, + xmlCatalogEntryType type = XML_CATA_NONE; + + cur = xmlParseSGMLCatalogName(cur, &name); +- if (name == NULL) { ++ if (cur == NULL || name == NULL) { + /* error */ + break; + } +@@ -3254,6 +3253,7 @@ xmlLoadCatalogs(const char *pathss) { + while ((*cur != 0) && (*cur != PATH_SEPARATOR) && (!xmlIsBlank_ch(*cur))) + cur++; + path = xmlStrndup((const xmlChar *)paths, cur - paths); ++ if (path != NULL) { + #ifdef _WIN32 + iLen = strlen((const char*)path); + for(i = 0; i < iLen; i++) { +@@ -3262,7 +3262,6 @@ xmlLoadCatalogs(const char *pathss) { + } + } + #endif +- if (path != NULL) { + xmlLoadCatalog((const char *) path); + xmlFree(path); + } +@@ -3427,9 +3426,10 @@ xmlCatalogAdd(const xmlChar *type, const xmlChar *orig, const xmlChar *replace) + (xmlStrEqual(type, BAD_CAST "catalog"))) { + xmlDefaultCatalog = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE, + xmlCatalogDefaultPrefer); +- xmlDefaultCatalog->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, ++ if (xmlDefaultCatalog != NULL) { ++ xmlDefaultCatalog->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, + orig, NULL, xmlCatalogDefaultPrefer, NULL); +- ++ } + xmlRMutexUnlock(xmlCatalogMutex); + return(0); + } +-- +1.8.3.1 + diff --git a/Use-random-seed-in-xmlDictComputeFastKey.patch b/Use-random-seed-in-xmlDictComputeFastKey.patch new file mode 100644 index 0000000000000000000000000000000000000000..2b178831166488ef42a4c9bb34fd49030959b7be --- /dev/null +++ b/Use-random-seed-in-xmlDictComputeFastKey.patch @@ -0,0 +1,27 @@ +From 3c8a3e9922cb1203ab5998ec542ce1e4c7fd085a Mon Sep 17 00:00:00 2001 +From: Ranier Vilela +Date: Thu, 7 Nov 2019 12:59:10 +0000 +Subject: [PATCH] Use random seed in xmlDictComputeFastKey + +xmlDictComputeFastKey is only used for small tables, so this shouldn't +be a security problem. +--- + dict.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/dict.c b/dict.c +index 336e046..26ce516 100644 +--- a/dict.c ++++ b/dict.c +@@ -452,7 +452,7 @@ xmlDictComputeFastKey(const xmlChar *name, int namelen, int seed) { + unsigned long value = seed; + + if (name == NULL) return(0); +- value = *name; ++ value += *name; + value <<= 5; + if (namelen > 10) { + value += name[namelen - 1]; +-- +1.8.3.1 + diff --git a/libxml2.spec b/libxml2.spec index 8c091103f69ea2b0f53a79c03fbe9347e7e97885..33d03b5ad821a97e4723dac74634f001351cbced 100644 --- a/libxml2.spec +++ b/libxml2.spec @@ -1,7 +1,7 @@ Summary: Library providing XML and HTML support Name: libxml2 Version: 2.9.10 -Release: 1 +Release: 2 License: MIT Group: Development/Libraries Source: ftp://xmlsoft.org/libxml2/libxml2-%{version}.tar.gz @@ -10,6 +10,20 @@ Patch0: libxml2-multilib.patch Patch6001: backport-Fix-memory-leak-in-xmlSchemaValidateStream.patch Patch6002: backport-fix-infinite-loop-in-xmlStringLenDecodeEntities.patch Patch6003: backport-Updated-python-tests-tstLastError.py.patch +Patch0004: Null-pointer-handling-in-catalog-c.patch +Patch0005: Fix-overflow-handling-in-xmlBufBackToBuffer.patch +Patch0006: Fix-memory-leak-in-error-path-of-XPath-expr-parser.patch +Patch0007: Fix-memory-leaks-of-encoding-handlers-in-xmlsave-c.patch +Patch0008: Use-random-seed-in-xmlDictComputeFastKey.patch +Patch0009: Fix-more-memory-leaks-in-error-paths-of-XPath-parser.patch +Patch0010: Fix-freeing-of-nested-documents.patch +Patch0011: Fix-overflow-check-in-xmlNodeDump.patch +Patch0012: Check-for-overflow-when-allocating-two-dimensional-a.patch +Patch0013: Fix-integer-overflow-in-xmlBufferResize.patch +Patch0014: Fix-copying-of-entities-in-xmlParseReference.patch +Patch0015: Copy-some-XMLReader-option-flags-to-parser-context.patch +Patch0016: Merge-code-paths-loading-external-entities.patch +Patch0017: Don-t-load-external-entity-from-xmlSAX2GetEntity.patch BuildRoot: %{_tmppath}/%{name}-%{version}-root BuildRequires: python2-devel @@ -201,6 +215,9 @@ rm -fr %{buildroot} %changelog +* Wed Jun 24 2020 wangchen - 2.9.10-2 +- Sync some patches from community + * Fri Apr 24 2020 BruceGW - 2.9.10-1 - update upstream to 2.9.10