File php7-CVE-2023-3823.patch of Package php7.35979

Index: php-7.4.33/ext/dom/document.c
===================================================================
--- php-7.4.33.orig/ext/dom/document.c
+++ php-7.4.33/ext/dom/document.c
@@ -1458,6 +1458,7 @@ static xmlDocPtr dom_document_parser(zva
 		options |= XML_PARSE_NOBLANKS;
 	}
 
+	php_libxml_sanitize_parse_ctxt_options(ctxt);
 	xmlCtxtUseOptions(ctxt, options);
 
 	ctxt->recovery = recover;
@@ -1758,7 +1759,9 @@ PHP_FUNCTION(dom_document_xinclude)
 
 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
 
+	PHP_LIBXML_SANITIZE_GLOBALS(xinclude);
 	err = xmlXIncludeProcessFlags(docp, (int)flags);
+	PHP_LIBXML_RESTORE_GLOBALS(xinclude);
 
 	/* XML_XINCLUDE_START and XML_XINCLUDE_END nodes need to be removed as these
 	are added via xmlXIncludeProcess to mark beginning and ending of xincluded document
@@ -1798,6 +1801,7 @@ PHP_FUNCTION(dom_document_validate)
 
 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
 
+	PHP_LIBXML_SANITIZE_GLOBALS(validate);
 	cvp = xmlNewValidCtxt();
 
 	cvp->userData = NULL;
@@ -1809,6 +1813,7 @@ PHP_FUNCTION(dom_document_validate)
 	} else {
 		RETVAL_FALSE;
 	}
+	PHP_LIBXML_RESTORE_GLOBALS(validate);
 
 	xmlFreeValidCtxt(cvp);
 
@@ -1843,14 +1848,18 @@ static void _dom_document_schema_validat
 
 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
 
+	PHP_LIBXML_SANITIZE_GLOBALS(new_parser_ctxt);
+
 	switch (type) {
 	case DOM_LOAD_FILE:
 		if (CHECK_NULL_PATH(source, source_len)) {
+			PHP_LIBXML_RESTORE_GLOBALS(new_parser_ctxt);
 			php_error_docref(NULL, E_WARNING, "Invalid Schema file source");
 			RETURN_FALSE;
 		}
 		valid_file = _dom_get_valid_file_path(source, resolved_path, MAXPATHLEN);
 		if (!valid_file) {
+			PHP_LIBXML_RESTORE_GLOBALS(new_parser_ctxt);
 			php_error_docref(NULL, E_WARNING, "Invalid Schema file source");
 			RETURN_FALSE;
 		}
@@ -1871,6 +1880,7 @@ static void _dom_document_schema_validat
 		parser);
 	sptr = xmlSchemaParse(parser);
 	xmlSchemaFreeParserCtxt(parser);
+	PHP_LIBXML_RESTORE_GLOBALS(new_parser_ctxt);
 	if (!sptr) {
 		php_error_docref(NULL, E_WARNING, "Invalid Schema");
 		RETURN_FALSE;
@@ -1889,11 +1899,13 @@ static void _dom_document_schema_validat
 		valid_opts |= XML_SCHEMA_VAL_VC_I_CREATE;
 	}
 
+	PHP_LIBXML_SANITIZE_GLOBALS(validate);
 	xmlSchemaSetValidOptions(vptr, valid_opts);
 	xmlSchemaSetValidErrors(vptr, php_libxml_error_handler, php_libxml_error_handler, vptr);
 	is_valid = xmlSchemaValidateDoc(vptr, docp);
 	xmlSchemaFree(sptr);
 	xmlSchemaFreeValidCtxt(vptr);
+	PHP_LIBXML_RESTORE_GLOBALS(validate);
 
 	if (is_valid == 0) {
 		RETURN_TRUE;
@@ -1964,12 +1976,14 @@ static void _dom_document_relaxNG_valida
 		return;
 	}
 
+	PHP_LIBXML_SANITIZE_GLOBALS(parse);
 	xmlRelaxNGSetParserErrors(parser,
 		(xmlRelaxNGValidityErrorFunc) php_libxml_error_handler,
 		(xmlRelaxNGValidityWarningFunc) php_libxml_error_handler,
 		parser);
 	sptr = xmlRelaxNGParse(parser);
 	xmlRelaxNGFreeParserCtxt(parser);
+	PHP_LIBXML_RESTORE_GLOBALS(parse);
 	if (!sptr) {
 		php_error_docref(NULL, E_WARNING, "Invalid RelaxNG");
 		RETURN_FALSE;
@@ -2068,6 +2082,7 @@ static void dom_load_html(INTERNAL_FUNCT
 		ctxt->sax->error = php_libxml_ctx_error;
 		ctxt->sax->warning = php_libxml_ctx_warning;
 	}
+	php_libxml_sanitize_parse_ctxt_options(ctxt);
 	if (options) {
 		htmlCtxtUseOptions(ctxt, (int)options);
 	}
Index: php-7.4.33/ext/dom/documentfragment.c
===================================================================
--- php-7.4.33.orig/ext/dom/documentfragment.c
+++ php-7.4.33/ext/dom/documentfragment.c
@@ -131,7 +131,9 @@ PHP_METHOD(domdocumentfragment, appendXM
 	}
 
 	if (data) {
+		PHP_LIBXML_SANITIZE_GLOBALS(parse);
 		err = xmlParseBalancedChunkMemory(nodep->doc, NULL, NULL, 0, (xmlChar *) data, &lst);
+		PHP_LIBXML_RESTORE_GLOBALS(parse);
 		if (err != 0) {
 			RETURN_FALSE;
 		}
Index: php-7.4.33/ext/libxml/php_libxml.h
===================================================================
--- php-7.4.33.orig/ext/libxml/php_libxml.h
+++ php-7.4.33/ext/libxml/php_libxml.h
@@ -120,6 +120,42 @@ PHP_LIBXML_API void php_libxml_shutdown(
 ZEND_TSRMLS_CACHE_EXTERN()
 #endif
 
+/* Other extension may override the global state options, these global options
+ * are copied initially to ctxt->options. Set the options to a known good value.
+ * See libxml2 globals.c and parserInternals.c.
+ * The unique_name argument allows multiple sanitizes and restores within the
+ * same function, even nested is necessary. */
+#define PHP_LIBXML_SANITIZE_GLOBALS(unique_name) \
+	int xml_old_loadsubset_##unique_name = xmlLoadExtDtdDefaultValue; \
+	xmlLoadExtDtdDefaultValue = 0; \
+	int xml_old_validate_##unique_name = xmlDoValidityCheckingDefaultValue; \
+	xmlDoValidityCheckingDefaultValue = 0; \
+	int xml_old_pedantic_##unique_name = xmlPedanticParserDefault(0); \
+	int xml_old_substitute_##unique_name = xmlSubstituteEntitiesDefault(0); \
+	int xml_old_linenrs_##unique_name = xmlLineNumbersDefault(0); \
+	int xml_old_blanks_##unique_name = xmlKeepBlanksDefault(1);
+
+#define PHP_LIBXML_RESTORE_GLOBALS(unique_name) \
+	xmlLoadExtDtdDefaultValue = xml_old_loadsubset_##unique_name; \
+	xmlDoValidityCheckingDefaultValue = xml_old_validate_##unique_name; \
+	(void) xmlPedanticParserDefault(xml_old_pedantic_##unique_name); \
+	(void) xmlSubstituteEntitiesDefault(xml_old_substitute_##unique_name); \
+	(void) xmlLineNumbersDefault(xml_old_linenrs_##unique_name); \
+	(void) xmlKeepBlanksDefault(xml_old_blanks_##unique_name);
+
+/* Alternative for above, working directly on the context and not setting globals.
+ * Generally faster because no locking is involved, and this has the advantage that it sets the options to a known good value. */
+static zend_always_inline void php_libxml_sanitize_parse_ctxt_options(xmlParserCtxtPtr ctxt)
+{
+	ctxt->loadsubset = 0;
+	ctxt->validate = 0;
+	ctxt->pedantic = 0;
+	ctxt->replaceEntities = 0;
+	ctxt->linenumbers = 0;
+	ctxt->keepBlanks = 1;
+	ctxt->options = 0;
+}
+
 #else /* HAVE_LIBXML */
 #define libxml_module_ptr NULL
 #endif
Index: php-7.4.33/ext/simplexml/simplexml.c
===================================================================
--- php-7.4.33.orig/ext/simplexml/simplexml.c
+++ php-7.4.33/ext/simplexml/simplexml.c
@@ -2194,7 +2194,9 @@ PHP_FUNCTION(simplexml_load_file)
 		RETURN_FALSE;
 	}
 
+	PHP_LIBXML_SANITIZE_GLOBALS(read_file);
 	docp = xmlReadFile(filename, NULL, (int)options);
+	PHP_LIBXML_RESTORE_GLOBALS(read_file);
 
 	if (!docp) {
 		RETURN_FALSE;
@@ -2248,7 +2250,9 @@ PHP_FUNCTION(simplexml_load_string)
 		RETURN_FALSE;
 	}
 
+	PHP_LIBXML_SANITIZE_GLOBALS(read_memory);
 	docp = xmlReadMemory(data, (int)data_len, NULL, NULL, (int)options);
+	PHP_LIBXML_RESTORE_GLOBALS(read_memory);
 
 	if (!docp) {
 		RETURN_FALSE;
@@ -2298,7 +2302,9 @@ SXE_METHOD(__construct)
 		return;
 	}
 
+	PHP_LIBXML_SANITIZE_GLOBALS(read_file_or_memory);
 	docp = is_url ? xmlReadFile(data, NULL, (int)options) : xmlReadMemory(data, (int)data_len, NULL, NULL, (int)options);
+	PHP_LIBXML_RESTORE_GLOBALS(read_file_or_memory);
 
 	if (!docp) {
 		((php_libxml_node_object *)sxe)->document = NULL;
Index: php-7.4.33/ext/soap/php_xml.c
===================================================================
--- php-7.4.33.orig/ext/soap/php_xml.c
+++ php-7.4.33/ext/soap/php_xml.c
@@ -93,6 +93,7 @@ xmlDocPtr soap_xmlParseFile(const char *
 	if (ctxt) {
 		zend_bool old;
 
+		php_libxml_sanitize_parse_ctxt_options(ctxt);
 		ctxt->keepBlanks = 0;
 		ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace;
 		ctxt->sax->comment = soap_Comment;
@@ -141,6 +142,7 @@ xmlDocPtr soap_xmlParseMemory(const void
 	if (ctxt) {
 		zend_bool old;
 
+		php_libxml_sanitize_parse_ctxt_options(ctxt);
 		ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace;
 		ctxt->sax->comment = soap_Comment;
 		ctxt->sax->warning = NULL;
Index: php-7.4.33/ext/xml/compat.c
===================================================================
--- php-7.4.33.orig/ext/xml/compat.c
+++ php-7.4.33/ext/xml/compat.c
@@ -19,6 +19,7 @@
 #include "php.h"
 #if defined(HAVE_LIBXML) && (defined(HAVE_XML) || defined(HAVE_XMLRPC)) && !defined(HAVE_LIBEXPAT)
 #include "expat_compat.h"
+#include "ext/libxml/php_libxml.h"
 
 typedef struct _php_xml_ns {
 	xmlNsPtr nsptr;
@@ -471,6 +472,7 @@ XML_ParserCreate_MM(const XML_Char *enco
 		return NULL;
 	}
 
+	php_libxml_sanitize_parse_ctxt_options(parser->parser);
 	xmlCtxtUseOptions(parser->parser, XML_PARSE_OLDSAX);
 
 	parser->parser->replaceEntities = 1;
Index: php-7.4.33/ext/xmlreader/php_xmlreader.c
===================================================================
--- php-7.4.33.orig/ext/xmlreader/php_xmlreader.c
+++ php-7.4.33/ext/xmlreader/php_xmlreader.c
@@ -304,6 +304,7 @@ static xmlRelaxNGPtr _xmlreader_get_rela
 		return NULL;
 	}
 
+	PHP_LIBXML_SANITIZE_GLOBALS(parse);
 	if (error_func || warn_func) {
 		xmlRelaxNGSetParserErrors(parser,
 			(xmlRelaxNGValidityErrorFunc) error_func,
@@ -312,6 +313,7 @@ static xmlRelaxNGPtr _xmlreader_get_rela
 	}
 	sptr = xmlRelaxNGParse(parser);
 	xmlRelaxNGFreeParserCtxt(parser);
+	PHP_LIBXML_RESTORE_GLOBALS(parse);
 
 	return sptr;
 }
@@ -881,7 +883,9 @@ PHP_METHOD(xmlreader, open)
 	valid_file = _xmlreader_get_valid_file_path(source, resolved_path, MAXPATHLEN );
 
 	if (valid_file) {
+		PHP_LIBXML_SANITIZE_GLOBALS(reader_for_file);
 		reader = xmlReaderForFile(valid_file, encoding, options);
+		PHP_LIBXML_RESTORE_GLOBALS(reader_for_file);
 	}
 
 	if (reader == NULL) {
@@ -958,7 +962,9 @@ PHP_METHOD(xmlreader, setSchema)
 
 	intern = Z_XMLREADER_P(id);
 	if (intern && intern->ptr) {
+		PHP_LIBXML_SANITIZE_GLOBALS(schema);
 		retval = xmlTextReaderSchemaValidate(intern->ptr, source);
+		PHP_LIBXML_RESTORE_GLOBALS(schema);
 
 		if (retval == 0) {
 			RETURN_TRUE;
@@ -1082,6 +1088,7 @@ PHP_METHOD(xmlreader, XML)
 			}
 			uri = (char *) xmlCanonicPath((const xmlChar *) resolved_path);
 		}
+		PHP_LIBXML_SANITIZE_GLOBALS(text_reader);
 		reader = xmlNewTextReader(inputbfr, uri);
 
 		if (reader != NULL) {
@@ -1100,9 +1107,11 @@ PHP_METHOD(xmlreader, XML)
 					xmlFree(uri);
 				}
 
+				PHP_LIBXML_RESTORE_GLOBALS(text_reader);
 				return;
 			}
 		}
+		PHP_LIBXML_RESTORE_GLOBALS(text_reader);
 	}
 
 	if (uri) {
Index: php-7.4.33/ext/xsl/xsltprocessor.c
===================================================================
--- php-7.4.33.orig/ext/xsl/xsltprocessor.c
+++ php-7.4.33/ext/xsl/xsltprocessor.c
@@ -398,7 +398,7 @@ PHP_FUNCTION(xsl_xsltprocessor_import_st
 	xmlDoc *doc = NULL, *newdoc = NULL;
 	xsltStylesheetPtr sheetp, oldsheetp;
 	xsl_object *intern;
-	int prevSubstValue, prevExtDtdValue, clone_docu = 0;
+	int clone_docu = 0;
 	xmlNode *nodep = NULL;
 	zval *cloneDocu, member, rv;
 
@@ -421,13 +421,12 @@ PHP_FUNCTION(xsl_xsltprocessor_import_st
 	stylesheet document otherwise the node proxies will be a mess */
 	newdoc = xmlCopyDoc(doc, 1);
 	xmlNodeSetBase((xmlNodePtr) newdoc, (xmlChar *)doc->URL);
-	prevSubstValue = xmlSubstituteEntitiesDefault(1);
-	prevExtDtdValue = xmlLoadExtDtdDefaultValue;
+	PHP_LIBXML_SANITIZE_GLOBALS(parse);
+	xmlSubstituteEntitiesDefault(1);
 	xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
 
 	sheetp = xsltParseStylesheetDoc(newdoc);
-	xmlSubstituteEntitiesDefault(prevSubstValue);
-	xmlLoadExtDtdDefaultValue = prevExtDtdValue;
+	PHP_LIBXML_RESTORE_GLOBALS(parse);
 
 	if (!sheetp) {
 		xmlFreeDoc(newdoc);
openSUSE Build Service is sponsored by