Roll libxml from e08d8c37 to 5930fe01

2022-07-18 wellnhofer@aevum.de Reset nsNr in xmlCtxtReset
2022-07-13 daniel.engberg.lists@pyret.net cmake: Install libxml.m4 on UNIX-like platforms
2022-07-13 daniel.engberg.lists@pyret.net cmake: Use symbol versioning on UNIX-like platforms
2022-07-06 sergey.kosukhin@mpimet.mpg.de Use NAN/INFINITY if available to init XPath NaN/Inf
2022-06-28 wellnhofer@aevum.de Fix memory leak in xmlLoadEntityContent error path
2022-06-28 wellnhofer@aevum.de Avoid double-free if malloc fails in inputPush
2022-05-20 wellnhofer@aevum.de Avoid calling xmlSetTreeDoc
2022-05-20 wellnhofer@aevum.de Simplify xmlFreeNode
2022-05-18 wellnhofer@aevum.de Don't reset nsDef when changing node content
2022-05-18 wellnhofer@aevum.de Fix unintended fall-through in xmlNodeAddContentLen
2022-05-14 wellnhofer@aevum.de Fix Python tests on macOS
2022-05-13 ddkilzer@apple.com Reserve byte for NUL terminator and report errors consistently in xmlBuf and xmlBuffer
2022-05-29 ddkilzer@apple.com Fix missing NUL terminators in xmlBuf and xmlBuffer functions
2022-06-15 wellnhofer@aevum.de Fix xmlCleanupThreads on Windows
2022-06-14 wellnhofer@aevum.de Fix reinitialization of library on Windows
2022-05-28 ddkilzer@apple.com Fix integer overflow in xmlBufferDump()
2022-05-25 ddkilzer@apple.com xmlBufAvail() should return length without including a byte for NUL terminator
2022-05-25 ddkilzer@apple.com Remove unused xmlBuf functions
2022-05-25 ddkilzer@apple.com Fix double colon typos in xmlBufferResize()
2022-03-19 ddkilzer@apple.com Fix ownership of xmlNodePtr & xmlAttrPtr fields in xmlSetTreeDoc()
2022-05-20 wellnhofer@aevum.de Use xmlNewDocText in xmlXIncludeCopyRange
2022-05-20 wellnhofer@aevum.de Disable network in API tests
2022-04-10 ddkilzer@apple.com Fix use-after-free bugs when calling xmlTextReaderClose() before xmlFreeTextReader() on post-validating parser
2022-05-14 ddkilzer@apple.com Restore behavior of htmlDocContentDumpFormatOutput()

Bug: 934413
Change-Id: I541ec92a85e5544963fe1bb8830a8ba752fb1a14
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3771046
Reviewed-by: Stephen Chenney <schenney@chromium.org>
Commit-Queue: Joey Arhar <jarhar@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1025761}
NOKEYCHECK=True
GitOrigin-RevId: 1043bbc6d43972bb99e43baa7f5499a82f19d938
diff --git a/README.chromium b/README.chromium
index e5aaeaf..ca58321 100644
--- a/README.chromium
+++ b/README.chromium
@@ -1,6 +1,6 @@
 Name: libxml
 URL: http://xmlsoft.org
-Version: e08d8c37f596fd254520361d65306e17c9e4b053
+Version: 5930fe01963136ab92125feec0c6204d9c9225dc
 CPEPrefix: cpe:/a:xmlsoft:libxml2:2.9.13
 License: MIT
 License File: src/Copyright
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 2b5425e..e3d7c93 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -367,6 +367,12 @@
 	set(XML_CFLAGS "-DLIBXML_STATIC")
 endif()
 
+if(BUILD_SHARED_LIBS AND UNIX)
+	if(CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "GNU")
+		target_link_options(LibXml2 PRIVATE "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/libxml2.syms")
+	endif()
+endif()
+
 if(LIBXML2_WITH_THREADS)
 	target_compile_definitions(LibXml2 PRIVATE _REENTRANT)
 	if(WIN32)
@@ -671,6 +677,10 @@
 configure_file(xml2-config.in xml2-config @ONLY)
 install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/xml2-config DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT development)
 
+if(UNIX)
+	install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/libxml.m4 DESTINATION ${CMAKE_INSTALL_DATADIR}/aclocal)
+endif()
+
 set(XML_INCLUDEDIR "-I${CMAKE_INSTALL_FULL_INCLUDEDIR}/libxml2")
 set(XML_LIBDIR "-L${CMAKE_INSTALL_FULL_LIBDIR}")
 
diff --git a/src/HTMLtree.c b/src/HTMLtree.c
index 91f4b9b..3dd78a9 100644
--- a/src/HTMLtree.c
+++ b/src/HTMLtree.c
@@ -987,7 +987,14 @@
 htmlDocContentDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr cur,
 	                       const char *encoding ATTRIBUTE_UNUSED,
                                int format) {
+    int type = 0;
+    if (cur) {
+        type = cur->type;
+        cur->type = XML_HTML_DOCUMENT_NODE;
+    }
     htmlNodeDumpFormatOutput(buf, cur, (xmlNodePtr) cur, NULL, format);
+    if (cur)
+        cur->type = (xmlElementType) type;
 }
 
 /**
diff --git a/src/SAX2.c b/src/SAX2.c
index 6180f00..ec89046 100644
--- a/src/SAX2.c
+++ b/src/SAX2.c
@@ -2633,9 +2633,10 @@
 	    }
 	} else {
 	    /* Mixed content, first time */
-            if (type == XML_TEXT_NODE)
+            if (type == XML_TEXT_NODE) {
                 lastChild = xmlSAX2TextNode(ctxt, ch, len);
-            else
+                lastChild->doc = ctxt->myDoc;
+            } else
                 lastChild = xmlNewCDataBlock(ctxt->myDoc, ch, len);
 	    if (lastChild != NULL) {
 		xmlAddChild(ctxt->node, lastChild);
diff --git a/src/buf.c b/src/buf.c
index 2b1fd79..6749d97 100644
--- a/src/buf.c
+++ b/src/buf.c
@@ -436,9 +436,11 @@
 
     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
     if (len < buf->size - buf->use)
-        return(buf->size - buf->use);
-    if (len > SIZE_MAX - buf->use)
+        return(buf->size - buf->use - 1);
+    if (len >= SIZE_MAX - buf->use) {
+        xmlBufMemoryError(buf, "growing buffer past SIZE_MAX");
         return(0);
+    }
 
     if (buf->size > (size_t) len) {
         size = buf->size > SIZE_MAX / 2 ? SIZE_MAX : buf->size * 2;
@@ -451,7 +453,7 @@
         /*
 	 * Used to provide parsing limits
 	 */
-        if ((buf->use + len >= XML_MAX_TEXT_LENGTH) ||
+        if ((buf->use + len + 1 >= XML_MAX_TEXT_LENGTH) ||
 	    (buf->size >= XML_MAX_TEXT_LENGTH)) {
 	    xmlBufMemoryError(buf, "buffer error: text too long\n");
 	    return(0);
@@ -479,7 +481,7 @@
     }
     buf->size = size;
     UPDATE_COMPAT(buf)
-    return(buf->size - buf->use);
+    return(buf->size - buf->use - 1);
 }
 
 /**
@@ -506,24 +508,6 @@
 }
 
 /**
- * xmlBufInflate:
- * @buf:  the buffer
- * @len:  the minimum extra free size to allocate
- *
- * Grow the available space of an XML buffer, adding at least @len bytes
- *
- * Returns 0 if successful or -1 in case of error
- */
-int
-xmlBufInflate(xmlBufPtr buf, size_t len) {
-    if (buf == NULL) return(-1);
-    xmlBufGrowInternal(buf, len + buf->size);
-    if (buf->error)
-        return(-1);
-    return(0);
-}
-
-/**
  * xmlBufDump:
  * @file:  the file output
  * @buf:  the buffer to dump
@@ -609,34 +593,9 @@
     if ((buf == NULL) || (buf->error))
         return(-1);
     CHECK_COMPAT(buf)
-    if (len > (buf->size - buf->use))
+    if (len >= (buf->size - buf->use))
         return(-1);
     buf->use += len;
-    UPDATE_COMPAT(buf)
-    if (buf->size > buf->use)
-        buf->content[buf->use] = 0;
-    else
-        return(-1);
-    return(0);
-}
-
-/**
- * xmlBufErase:
- * @buf:  the buffer
- * @len:  the size to erase at the end
- *
- * Sometime data need to be erased at the end of the buffer
- *
- * Returns -1 in case of error and 0 otherwise
- */
-int
-xmlBufErase(xmlBufPtr buf, size_t len) {
-    if ((buf == NULL) || (buf->error))
-        return(-1);
-    CHECK_COMPAT(buf)
-    if (len > buf->use)
-        return(-1);
-    buf->use -= len;
     buf->content[buf->use] = 0;
     UPDATE_COMPAT(buf)
     return(0);
@@ -685,10 +644,11 @@
  * @buf:  the buffer
  *
  * Function to find how much free space is allocated but not
- * used in the buffer. It does not account for the terminating zero
- * usually needed
+ * used in the buffer. It reserves one byte for the NUL
+ * terminator character that is usually needed, so there is
+ * no need to subtract 1 from the result anymore.
  *
- * Returns the amount or 0 if none or an error occurred
+ * Returns the amount, or 0 if none or if an error occurred.
  */
 
 size_t
@@ -698,7 +658,7 @@
         return 0;
     CHECK_COMPAT(buf)
 
-    return(buf->size - buf->use);
+    return((buf->size > buf->use) ? (buf->size - buf->use - 1) : 0);
 }
 
 /**
@@ -816,6 +776,8 @@
     } else {
 	if (buf->content == NULL) {
 	    rebuf = (xmlChar *) xmlMallocAtomic(newSize);
+	    buf->use = 0;
+	    rebuf[buf->use] = 0;
 	} else if (buf->size - buf->use < 100) {
 	    rebuf = (xmlChar *) xmlRealloc(buf->content, newSize);
         } else {
@@ -879,9 +841,12 @@
     if (len < 0) return -1;
     if (len == 0) return 0;
 
+    /* Note that both buf->size and buf->use can be zero here. */
     if ((size_t) len >= buf->size - buf->use) {
-        if ((size_t) len >= SIZE_MAX - buf->use)
+        if ((size_t) len >= SIZE_MAX - buf->use) {
+            xmlBufMemoryError(buf, "growing buffer past SIZE_MAX");
             return(-1);
+        }
         needSize = buf->use + len + 1;
 	if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
 	    /*
@@ -906,87 +871,6 @@
 }
 
 /**
- * xmlBufAddHead:
- * @buf:  the buffer
- * @str:  the #xmlChar string
- * @len:  the number of #xmlChar to add
- *
- * Add a string range to the beginning of an XML buffer.
- * if len == -1, the length of @str is recomputed.
- *
- * Returns 0 successful, a positive error code number otherwise
- *         and -1 in case of internal or API error.
- */
-int
-xmlBufAddHead(xmlBufPtr buf, const xmlChar *str, int len) {
-    unsigned int needSize;
-
-    if ((buf == NULL) || (buf->error))
-        return(-1);
-    CHECK_COMPAT(buf)
-    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
-    if (str == NULL) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufAddHead: str == NULL\n");
-#endif
-	return -1;
-    }
-    if (len < -1) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufAddHead: len < 0\n");
-#endif
-	return -1;
-    }
-    if (len == 0) return 0;
-
-    if (len < 0)
-        len = xmlStrlen(str);
-
-    if (len <= 0) return -1;
-
-    if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
-        size_t start_buf = buf->content - buf->contentIO;
-
-	if (start_buf > (unsigned int) len) {
-	    /*
-	     * We can add it in the space previously shrunk
-	     */
-	    buf->content -= len;
-            memmove(&buf->content[0], str, len);
-	    buf->use += len;
-	    buf->size += len;
-	    UPDATE_COMPAT(buf)
-	    return(0);
-	}
-    }
-    needSize = buf->use + len + 2;
-    if (needSize > buf->size){
-	if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
-	    /*
-	     * Used to provide parsing limits
-	     */
-	    if (needSize >= XML_MAX_TEXT_LENGTH) {
-		xmlBufMemoryError(buf, "buffer error: text too long\n");
-		return(-1);
-	    }
-	}
-        if (!xmlBufResize(buf, needSize)){
-	    xmlBufMemoryError(buf, "growing buffer");
-            return XML_ERR_NO_MEMORY;
-        }
-    }
-
-    memmove(&buf->content[len], &buf->content[0], buf->use);
-    memmove(&buf->content[0], str, len);
-    buf->use += len;
-    buf->content[buf->use] = 0;
-    UPDATE_COMPAT(buf)
-    return 0;
-}
-
-/**
  * xmlBufCat:
  * @buf:  the buffer to add to
  * @str:  the #xmlChar string
@@ -1022,49 +906,6 @@
 }
 
 /**
- * xmlBufWriteCHAR:
- * @buf:  the XML buffer
- * @string:  the string to add
- *
- * routine which manages and grows an output buffer. This one adds
- * xmlChars at the end of the buffer.
- *
- * Returns 0 if successful, a positive error code number otherwise
- *         and -1 in case of internal or API error.
- */
-int
-xmlBufWriteCHAR(xmlBufPtr buf, const xmlChar *string) {
-    if ((buf == NULL) || (buf->error))
-        return(-1);
-    CHECK_COMPAT(buf)
-    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)
-        return(-1);
-    return(xmlBufCat(buf, string));
-}
-
-/**
- * xmlBufWriteChar:
- * @buf:  the XML buffer output
- * @string:  the string to add
- *
- * routine which manage and grows an output buffer. This one add
- * C chars at the end of the array.
- *
- * Returns 0 if successful, a positive error code number otherwise
- *         and -1 in case of internal or API error.
- */
-int
-xmlBufWriteChar(xmlBufPtr buf, const char *string) {
-    if ((buf == NULL) || (buf->error))
-        return(-1);
-    CHECK_COMPAT(buf)
-    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)
-        return(-1);
-    return(xmlBufCCat(buf, string));
-}
-
-
-/**
  * xmlBufWriteQuotedString:
  * @buf:  the XML buffer output
  * @string:  the string to add
diff --git a/src/buf.h b/src/buf.h
index ebdc978..b7bcf61 100644
--- a/src/buf.h
+++ b/src/buf.h
@@ -32,15 +32,11 @@
 
 /* size_t xmlBufShrink(xmlBufPtr buf, size_t len); */
 int xmlBufGrow(xmlBufPtr buf, int len);
-int xmlBufInflate(xmlBufPtr buf, size_t len);
 int xmlBufResize(xmlBufPtr buf, size_t len);
 
 int xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len);
-int xmlBufAddHead(xmlBufPtr buf, const xmlChar *str, int len);
 int xmlBufCat(xmlBufPtr buf, const xmlChar *str);
 int xmlBufCCat(xmlBufPtr buf, const char *str);
-int xmlBufWriteCHAR(xmlBufPtr buf, const xmlChar *string);
-int xmlBufWriteChar(xmlBufPtr buf, const char *string);
 int xmlBufWriteQuotedString(xmlBufPtr buf, const xmlChar *string);
 
 size_t xmlBufAvail(const xmlBufPtr buf);
@@ -48,7 +44,6 @@
 /* size_t xmlBufUse(const xmlBufPtr buf); */
 int xmlBufIsEmpty(const xmlBufPtr buf);
 int xmlBufAddLen(xmlBufPtr buf, size_t len);
-int xmlBufErase(xmlBufPtr buf, size_t len);
 
 /* const xmlChar * xmlBufContent(const xmlBuf *buf); */
 /* const xmlChar * xmlBufEnd(xmlBufPtr buf); */
diff --git a/src/encoding.c b/src/encoding.c
index 0a82049..5465359 100644
--- a/src/encoding.c
+++ b/src/encoding.c
@@ -2197,7 +2197,7 @@
     toconv = xmlBufUse(in);
     if (toconv == 0)
         return (0);
-    written = xmlBufAvail(out) - 1; /* count '\0' */
+    written = xmlBufAvail(out);
     /*
      * echo '<?xml version="1.0" encoding="UCS4"?>' | wc -c => 38
      * 45 chars should be sufficient to reach the end of the encoding
@@ -2215,7 +2215,7 @@
     }
     if (toconv * 2 >= written) {
         xmlBufGrow(out, toconv * 2);
-        written = xmlBufAvail(out) - 1;
+        written = xmlBufAvail(out);
     }
     if (written > 360)
         written = 360;
@@ -2307,13 +2307,9 @@
     if ((toconv > 64 * 1024) && (flush == 0))
         toconv = 64 * 1024;
     written = xmlBufAvail(out);
-    if (written > 0)
-        written--; /* count '\0' */
     if (toconv * 2 >= written) {
         xmlBufGrow(out, toconv * 2);
         written = xmlBufAvail(out);
-        if (written > 0)
-            written--; /* count '\0' */
     }
     if ((written > 128 * 1024) && (flush == 0))
         written = 128 * 1024;
@@ -2495,8 +2491,6 @@
 retry:
 
     written = xmlBufAvail(out);
-    if (written > 0)
-        written--; /* count '\0' */
 
     /*
      * First specific handling of the initialization call
@@ -2525,7 +2519,7 @@
         toconv = 64 * 1024;
     if (toconv * 4 >= written) {
         xmlBufGrow(out, toconv * 4);
-        written = xmlBufAvail(out) - 1;
+        written = xmlBufAvail(out);
     }
     if (written > 256 * 1024)
         written = 256 * 1024;
@@ -2600,7 +2594,7 @@
                              "&#%d;", cur);
             xmlBufShrink(in, len);
             xmlBufGrow(out, charrefLen * 4);
-            c_out = xmlBufAvail(out) - 1;
+            c_out = xmlBufAvail(out);
             c_in = charrefLen;
             ret = xmlEncOutputChunk(output->encoder, xmlBufEnd(out), &c_out,
                                     charref, &c_in);
diff --git a/src/fuzz/Makefile.in b/src/fuzz/Makefile.in
index 22a49ba..ee3ca2a 100644
--- a/src/fuzz/Makefile.in
+++ b/src/fuzz/Makefile.in
@@ -260,6 +260,7 @@
 EXEEXT = @EXEEXT@
 EXTRA_CFLAGS = @EXTRA_CFLAGS@
 FGREP = @FGREP@
+FILECMD = @FILECMD@
 FTP_OBJ = @FTP_OBJ@
 GREP = @GREP@
 HTML_OBJ = @HTML_OBJ@
diff --git a/src/libxml2.spec b/src/libxml2.spec
index fbcc032..430116c 100644
--- a/src/libxml2.spec
+++ b/src/libxml2.spec
@@ -203,6 +203,6 @@
 %endif # with_python3
 
 %changelog
-* Fri May  6 2022 Daniel Veillard <veillard@redhat.com>
+* Mon Jul 18 2022 Daniel Veillard <veillard@redhat.com>
 - upstream release 2.9.13
 
diff --git a/src/parser.c b/src/parser.c
index 5391c90..6552a06 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -1759,9 +1759,7 @@
                                              sizeof(ctxt->inputTab[0]));
         if (ctxt->inputTab == NULL) {
             xmlErrMemory(ctxt, NULL);
-	    xmlFreeInputStream(value);
 	    ctxt->inputMax /= 2;
-	    value = NULL;
             return (-1);
         }
     }
@@ -7246,7 +7244,8 @@
                     ent->owner = 1;
                     while (list != NULL) {
                         list->parent = (xmlNodePtr) ent;
-                        xmlSetTreeDoc(list, ent->doc);
+                        if (list->doc != ent->doc)
+                            xmlSetTreeDoc(list, ent->doc);
                         if (list->next == NULL)
                             ent->last = list;
                         list = list->next;
@@ -8107,6 +8106,7 @@
      */
     if (xmlPushInput(ctxt, input) < 0) {
         xmlBufferFree(buf);
+	xmlFreeInputStream(input);
 	return(-1);
     }
 
@@ -13601,7 +13601,7 @@
     ctxt->input_id = 2;
     ctxt->instate = XML_PARSER_CONTENT;
 
-    fake = xmlNewComment(NULL);
+    fake = xmlNewDocComment(node->doc, NULL);
     if (fake == NULL) {
         xmlFreeParserCtxt(ctxt);
 	return(XML_ERR_NO_MEMORY);
@@ -14838,6 +14838,8 @@
     ctxt->nameNr = 0;
     ctxt->name = NULL;
 
+    ctxt->nsNr = 0;
+
     DICT_FREE(ctxt->version);
     ctxt->version = NULL;
     DICT_FREE(ctxt->encoding);
diff --git a/src/testapi.c b/src/testapi.c
index c7a5b16..db968cd 100644
--- a/src/testapi.c
+++ b/src/testapi.c
@@ -142,6 +142,7 @@
     LIBXML_TEST_VERSION
 
     xmlSetStructuredErrorFunc(NULL, structured_errors);
+    xmlSetExternalEntityLoader(xmlNoNetExternalEntityLoader);
 
     if (argc >= 2) {
         if (!strcmp(argv[1], "-q")) {
diff --git a/src/threads.c b/src/threads.c
index c33150e..f462ebf 100644
--- a/src/threads.c
+++ b/src/threads.c
@@ -906,8 +906,10 @@
     if (libxml_is_threaded != 0)
         pthread_key_delete(globalkey);
     once_control = once_control_init;
-#elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
+#elif defined(HAVE_WIN32_THREADS)
+#if !defined(HAVE_COMPILER_TLS)
     if (globalkey != TLS_OUT_OF_INDEXES) {
+#if !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)
         xmlGlobalStateCleanupHelperParams *p;
 
         EnterCriticalSection(&cleanup_helpers_cs);
@@ -921,11 +923,17 @@
         }
         cleanup_helpers_head = 0;
         LeaveCriticalSection(&cleanup_helpers_cs);
+#endif
         TlsFree(globalkey);
         globalkey = TLS_OUT_OF_INDEXES;
     }
+#if !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)
     DeleteCriticalSection(&cleanup_helpers_cs);
 #endif
+#endif
+    run_once.done = 0;
+    run_once.control = 0;
+#endif
 }
 
 #ifdef LIBXML_THREAD_ENABLED
diff --git a/src/tree.c b/src/tree.c
index 689a6b6..da34685 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -2812,6 +2812,20 @@
     return(cur);
 }
 
+static const xmlChar *_copyStringForNewDictIfNeeded(xmlDictPtr oldDict, xmlDictPtr newDict, const xmlChar *oldValue) {
+    const xmlChar *newValue = oldValue;
+    if (oldValue) {
+        int oldDictOwnsOldValue = oldDict && (xmlDictOwns(oldDict, oldValue) == 1);
+        if (oldDictOwnsOldValue) {
+            if (newDict)
+                newValue = xmlDictLookup(newDict, oldValue, -1);
+            else
+                newValue = xmlStrdup(oldValue);
+        }
+    }
+    return newValue;
+}
+
 /**
  * xmlSetTreeDoc:
  * @tree:  the top element
@@ -2826,6 +2840,9 @@
     if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL))
 	return;
     if (tree->doc != doc) {
+        xmlDictPtr oldTreeDict = tree->doc ? tree->doc->dict : NULL;
+        xmlDictPtr newDict = doc ? doc->dict : NULL;
+
 	if(tree->type == XML_ELEMENT_NODE) {
 	    prop = tree->properties;
 	    while (prop != NULL) {
@@ -2833,7 +2850,11 @@
                     xmlRemoveID(tree->doc, prop);
                 }
 
-		prop->doc = doc;
+                if (prop->doc != doc) {
+                    xmlDictPtr oldPropDict = prop->doc ? prop->doc->dict : NULL;
+                    prop->name = _copyStringForNewDictIfNeeded(oldPropDict, newDict, prop->name);
+                    prop->doc = doc;
+                }
 		xmlSetListDoc(prop->children, doc);
 
                 /*
@@ -2862,6 +2883,10 @@
         } else if (tree->children != NULL) {
 	    xmlSetListDoc(tree->children, doc);
         }
+
+        tree->name = _copyStringForNewDictIfNeeded(oldTreeDict, newDict, tree->name);
+        tree->content = (xmlChar *)_copyStringForNewDictIfNeeded(oldTreeDict, NULL, tree->content);
+        /* FIXME: tree->ns should be updated as in xmlStaticCopyNode(). */
 	tree->doc = doc;
     }
 }
@@ -3803,18 +3828,18 @@
     if ((cur->children != NULL) &&
 	(cur->type != XML_ENTITY_REF_NODE))
 	xmlFreeNodeList(cur->children);
-    if (((cur->type == XML_ELEMENT_NODE) ||
-	 (cur->type == XML_XINCLUDE_START) ||
-	 (cur->type == XML_XINCLUDE_END)) &&
-	(cur->properties != NULL))
-	xmlFreePropList(cur->properties);
-    if ((cur->type != XML_ELEMENT_NODE) &&
-	(cur->content != NULL) &&
-	(cur->type != XML_ENTITY_REF_NODE) &&
-	(cur->type != XML_XINCLUDE_END) &&
-	(cur->type != XML_XINCLUDE_START) &&
-	(cur->content != (xmlChar *) &(cur->properties))) {
-	DICT_FREE(cur->content)
+
+    if ((cur->type == XML_ELEMENT_NODE) ||
+        (cur->type == XML_XINCLUDE_START) ||
+        (cur->type == XML_XINCLUDE_END)) {
+        if (cur->properties != NULL)
+            xmlFreePropList(cur->properties);
+        if (cur->nsDef != NULL)
+            xmlFreeNsList(cur->nsDef);
+    } else if ((cur->content != NULL) &&
+               (cur->type != XML_ENTITY_REF_NODE) &&
+               (cur->content != (xmlChar *) &(cur->properties))) {
+        DICT_FREE(cur->content)
     }
 
     /*
@@ -3827,11 +3852,6 @@
         (cur->type != XML_COMMENT_NODE))
 	DICT_FREE(cur->name)
 
-    if (((cur->type == XML_ELEMENT_NODE) ||
-	 (cur->type == XML_XINCLUDE_START) ||
-	 (cur->type == XML_XINCLUDE_END)) &&
-	(cur->nsDef != NULL))
-	xmlFreeNsList(cur->nsDef);
     xmlFree(cur);
 }
 
@@ -5735,7 +5755,6 @@
 	    } else
 		cur->content = NULL;
 	    cur->properties = NULL;
-	    cur->nsDef = NULL;
 	    break;
         case XML_DOCUMENT_NODE:
         case XML_HTML_DOCUMENT_NODE:
@@ -5810,7 +5829,6 @@
 	    } else
 		cur->content = NULL;
 	    cur->properties = NULL;
-	    cur->nsDef = NULL;
 	    break;
         case XML_DOCUMENT_NODE:
         case XML_DTD_NODE:
@@ -5860,7 +5878,7 @@
 	    xmlNodePtr last, newNode, tmp;
 
 	    last = cur->last;
-	    newNode = xmlNewTextLen(content, len);
+	    newNode = xmlNewDocTextLen(cur->doc, content, len);
 	    if (newNode != NULL) {
 		tmp = xmlAddChild(cur, newNode);
 		if (tmp != newNode)
@@ -5886,11 +5904,11 @@
 			    xmlDictOwns(cur->doc->dict, cur->content))) {
 		    cur->content = xmlStrncatNew(cur->content, content, len);
 		    cur->properties = NULL;
-		    cur->nsDef = NULL;
-		    break;
-		}
-		cur->content = xmlStrncat(cur->content, content, len);
+		} else {
+		    cur->content = xmlStrncat(cur->content, content, len);
+                }
             }
+	    break;
         case XML_DOCUMENT_NODE:
         case XML_DTD_NODE:
         case XML_HTML_DOCUMENT_NODE:
@@ -7346,8 +7364,10 @@
     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
     if (len < buf->size - buf->use)
         return(0);
-    if (len > UINT_MAX - buf->use)
+    if (len >= UINT_MAX - buf->use) {
+        xmlTreeErrMemory("growing buffer past UINT_MAX");
         return(-1);
+    }
 
     if (buf->size > (size_t) len) {
         size = buf->size > UINT_MAX / 2 ? UINT_MAX : buf->size * 2;
@@ -7375,7 +7395,7 @@
 	buf->content = newbuf;
     }
     buf->size = size;
-    return(buf->size - buf->use);
+    return(buf->size - buf->use - 1);
 }
 
 /**
@@ -7388,7 +7408,7 @@
  */
 int
 xmlBufferDump(FILE *file, xmlBufferPtr buf) {
-    int ret;
+    size_t ret;
 
     if (buf == NULL) {
 #ifdef DEBUG_BUFFER
@@ -7407,7 +7427,7 @@
     if (file == NULL)
 	file = stdout;
     ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
-    return(ret);
+    return(ret > INT_MAX ? INT_MAX : (int)ret);
 }
 
 /**
@@ -7472,7 +7492,7 @@
         return 1;
 
     if (size > UINT_MAX - 10) {
-        xmlTreeErrMemory("growing buffer");
+        xmlTreeErrMemory("growing buffer past UINT_MAX");
         return 0;
     }
 
@@ -7494,7 +7514,7 @@
 	    }
 	    break;
 	case XML_BUFFER_ALLOC_EXACT:
-	    newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10);;
+	    newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10);
 	    break;
         case XML_BUFFER_ALLOC_HYBRID:
             if (buf->use < BASE_BUFFER_SIZE)
@@ -7512,7 +7532,7 @@
             break;
 
 	default:
-	    newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10);;
+	    newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10);
 	    break;
     }
 
@@ -7537,6 +7557,8 @@
     } else {
 	if (buf->content == NULL) {
 	    rebuf = (xmlChar *) xmlMallocAtomic(newSize);
+	    buf->use = 0;
+	    rebuf[buf->use] = 0;
 	} else if (buf->size - buf->use < 100) {
 	    rebuf = (xmlChar *) xmlRealloc(buf->content, newSize);
         } else {
@@ -7598,9 +7620,12 @@
     if (len < 0) return -1;
     if (len == 0) return 0;
 
+    /* Note that both buf->size and buf->use can be zero here. */
     if ((unsigned) len >= buf->size - buf->use) {
-        if ((unsigned) len >= UINT_MAX - buf->use)
+        if ((unsigned) len >= UINT_MAX - buf->use) {
+            xmlTreeErrMemory("growing buffer past UINT_MAX");
             return XML_ERR_NO_MEMORY;
+        }
         needSize = buf->use + len + 1;
         if (!xmlBufferResize(buf, needSize)){
 	    xmlTreeErrMemory("growing buffer");
@@ -7665,11 +7690,17 @@
             memmove(&buf->content[0], str, len);
 	    buf->use += len;
 	    buf->size += len;
+            buf->content[buf->use] = 0;
 	    return(0);
 	}
     }
-    needSize = buf->use + len + 2;
-    if (needSize > buf->size){
+    /* Note that both buf->size and buf->use can be zero here. */
+    if ((unsigned) len >= buf->size - buf->use) {
+        if ((unsigned) len >= UINT_MAX - buf->use) {
+            xmlTreeErrMemory("growing buffer past UINT_MAX");
+            return(-1);
+        }
+        needSize = buf->use + len + 1;
         if (!xmlBufferResize(buf, needSize)){
 	    xmlTreeErrMemory("growing buffer");
             return XML_ERR_NO_MEMORY;
diff --git a/src/xmlIO.c b/src/xmlIO.c
index 823a0dd..16c29f5 100644
--- a/src/xmlIO.c
+++ b/src/xmlIO.c
@@ -3547,7 +3547,7 @@
 	 * how many bytes to consume and how many bytes to store.
 	 */
 	cons = len;
-	chunk = xmlBufAvail(out->buffer) - 1;
+	chunk = xmlBufAvail(out->buffer);
 
         /*
 	 * make sure we have enough room to save first, if this is
diff --git a/src/xmlreader.c b/src/xmlreader.c
index ba95813..b3299ce 100644
--- a/src/xmlreader.c
+++ b/src/xmlreader.c
@@ -2181,36 +2181,16 @@
 	xmlFree(reader->patternTab);
     }
 #endif
-    if (reader->faketext != NULL) {
-	xmlFreeNode(reader->faketext);
-    }
+    if (reader->mode != XML_TEXTREADER_MODE_CLOSED)
+        xmlTextReaderClose(reader);
     if (reader->ctxt != NULL) {
         if (reader->dict == reader->ctxt->dict)
 	    reader->dict = NULL;
-#ifdef LIBXML_VALID_ENABLED
-	if ((reader->ctxt->vctxt.vstateTab != NULL) &&
-	    (reader->ctxt->vctxt.vstateMax > 0)){
-#ifdef LIBXML_REGEXP_ENABLED
-            while (reader->ctxt->vctxt.vstateNr > 0)
-                xmlValidatePopElement(&reader->ctxt->vctxt, NULL, NULL, NULL);
-#endif /* LIBXML_REGEXP_ENABLED */
-	    xmlFree(reader->ctxt->vctxt.vstateTab);
-	    reader->ctxt->vctxt.vstateTab = NULL;
-	    reader->ctxt->vctxt.vstateMax = 0;
-	}
-#endif /* LIBXML_VALID_ENABLED */
-	if (reader->ctxt->myDoc != NULL) {
-	    if (reader->preserve == 0)
-		xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
-	    reader->ctxt->myDoc = NULL;
-	}
 	if (reader->allocs & XML_TEXTREADER_CTXT)
 	    xmlFreeParserCtxt(reader->ctxt);
     }
     if (reader->sax != NULL)
 	xmlFree(reader->sax);
-    if ((reader->input != NULL)  && (reader->allocs & XML_TEXTREADER_INPUT))
-	xmlFreeParserInputBuffer(reader->input);
     if (reader->buffer != NULL)
         xmlBufFree(reader->buffer);
     if (reader->entTab != NULL)
@@ -2241,7 +2221,23 @@
     reader->node = NULL;
     reader->curnode = NULL;
     reader->mode = XML_TEXTREADER_MODE_CLOSED;
+    if (reader->faketext != NULL) {
+        xmlFreeNode(reader->faketext);
+        reader->faketext = NULL;
+    }
     if (reader->ctxt != NULL) {
+#ifdef LIBXML_VALID_ENABLED
+	if ((reader->ctxt->vctxt.vstateTab != NULL) &&
+	    (reader->ctxt->vctxt.vstateMax > 0)){
+#ifdef LIBXML_REGEXP_ENABLED
+            while (reader->ctxt->vctxt.vstateNr > 0)
+                xmlValidatePopElement(&reader->ctxt->vctxt, NULL, NULL, NULL);
+#endif /* LIBXML_REGEXP_ENABLED */
+	    xmlFree(reader->ctxt->vctxt.vstateTab);
+	    reader->ctxt->vctxt.vstateTab = NULL;
+	    reader->ctxt->vctxt.vstateMax = 0;
+	}
+#endif /* LIBXML_VALID_ENABLED */
 	xmlStopParser(reader->ctxt);
 	if (reader->ctxt->myDoc != NULL) {
 	    if (reader->preserve == 0)
diff --git a/src/xmlsave.c b/src/xmlsave.c
index 7b55749..9b42c66 100644
--- a/src/xmlsave.c
+++ b/src/xmlsave.c
@@ -1379,7 +1379,7 @@
 		 (htmlIsBooleanAttr(cur->name))) {
 	    if (cur->children != NULL)
 		xmlFreeNode(cur->children);
-	    cur->children = xmlNewText(cur->name);
+	    cur->children = xmlNewDocText(cur->doc, cur->name);
 	    if (cur->children != NULL)
 		cur->children->parent = (xmlNodePtr) cur;
 	}
diff --git a/src/xpath.c b/src/xpath.c
index 49abd96..f334685 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -490,11 +490,17 @@
 ATTRIBUTE_NO_SANITIZE("float-divide-by-zero")
 void
 xmlXPathInit(void) {
+#if defined(NAN) && defined(INFINITY)
+    xmlXPathNAN = NAN;
+    xmlXPathPINF = INFINITY;
+    xmlXPathNINF = -INFINITY;
+#else
     /* MSVC doesn't allow division by zero in constant expressions. */
     double zero = 0.0;
     xmlXPathNAN = 0.0 / zero;
     xmlXPathPINF = 1.0 / zero;
     xmlXPathNINF = -xmlXPathPINF;
+#endif
 }
 
 /**