File mysql-connector-java-CVE-2021-2471.patch of Package mysql-connector-java.23086
Index: mysql-connector-java-8.0.25/src/main/user-impl/java/com/mysql/cj/jdbc/MysqlSQLXML.java
===================================================================
--- mysql-connector-java-8.0.25.orig/src/main/user-impl/java/com/mysql/cj/jdbc/MysqlSQLXML.java
+++ mysql-connector-java-8.0.25/src/main/user-impl/java/com/mysql/cj/jdbc/MysqlSQLXML.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2020, Oracle and/or its affiliates.
+ * Copyright (c) 2002, 2021, Oracle and/or its affiliates.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 2.0, as published by the
@@ -42,6 +42,7 @@ import java.io.Writer;
import java.sql.SQLException;
import java.sql.SQLXML;
+import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.stream.XMLInputFactory;
@@ -65,7 +66,9 @@ import javax.xml.transform.stream.Stream
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.helpers.XMLReaderFactory;
import com.mysql.cj.Messages;
import com.mysql.cj.exceptions.ExceptionInterceptor;
@@ -199,56 +202,54 @@ public class MysqlSQLXML implements SQLX
if (clazz == null || clazz.equals(SAXSource.class)) {
- InputSource inputSource = null;
-
- if (this.fromResultSet) {
- inputSource = new InputSource(this.owningResultSet.getCharacterStream(this.columnIndexOfXml));
- } else {
- inputSource = new InputSource(new StringReader(this.stringRep));
+ try {
+ XMLReader reader = XMLReaderFactory.createXMLReader();
+ // According to https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html
+ reader.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ setFeature(reader, "http://apache.org/xml/features/disallow-doctype-decl", true);
+ setFeature(reader, "http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+ setFeature(reader, "http://xml.org/sax/features/external-general-entities", false);
+ setFeature(reader, "http://xml.org/sax/features/external-parameter-entities", false);
+
+ return (T) new SAXSource(reader, this.fromResultSet ? new InputSource(this.owningResultSet.getCharacterStream(this.columnIndexOfXml))
+ : new InputSource(new StringReader(this.stringRep)));
+ } catch (SAXException ex) {
+ SQLException sqlEx = SQLError.createSQLException(ex.getMessage(), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, ex, this.exceptionInterceptor);
+ throw sqlEx;
}
- return (T) new SAXSource(inputSource);
} else if (clazz.equals(DOMSource.class)) {
try {
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
builderFactory.setNamespaceAware(true);
- DocumentBuilder builder = builderFactory.newDocumentBuilder();
- InputSource inputSource = null;
+ // According to https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html
+ setFeature(builderFactory, XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ setFeature(builderFactory, "http://apache.org/xml/features/disallow-doctype-decl", true);
+ setFeature(builderFactory, "http://xml.org/sax/features/external-general-entities", false);
+ setFeature(builderFactory, "http://xml.org/sax/features/external-parameter-entities", false);
+ setFeature(builderFactory, "http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+ builderFactory.setXIncludeAware(false);
+ builderFactory.setExpandEntityReferences(false);
- if (this.fromResultSet) {
- inputSource = new InputSource(this.owningResultSet.getCharacterStream(this.columnIndexOfXml));
- } else {
- inputSource = new InputSource(new StringReader(this.stringRep));
- }
+ builderFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
+
+ DocumentBuilder builder = builderFactory.newDocumentBuilder();
- return (T) new DOMSource(builder.parse(inputSource));
+ return (T) new DOMSource(builder.parse(this.fromResultSet ? new InputSource(this.owningResultSet.getCharacterStream(this.columnIndexOfXml))
+ : new InputSource(new StringReader(this.stringRep))));
} catch (Throwable t) {
SQLException sqlEx = SQLError.createSQLException(t.getMessage(), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, t, this.exceptionInterceptor);
throw sqlEx;
}
} else if (clazz.equals(StreamSource.class)) {
- Reader reader = null;
-
- if (this.fromResultSet) {
- reader = this.owningResultSet.getCharacterStream(this.columnIndexOfXml);
- } else {
- reader = new StringReader(this.stringRep);
- }
+ return (T) new StreamSource(this.fromResultSet ? this.owningResultSet.getCharacterStream(this.columnIndexOfXml) : new StringReader(this.stringRep));
- return (T) new StreamSource(reader);
} else if (clazz.equals(StAXSource.class)) {
try {
- Reader reader = null;
-
- if (this.fromResultSet) {
- reader = this.owningResultSet.getCharacterStream(this.columnIndexOfXml);
- } else {
- reader = new StringReader(this.stringRep);
- }
-
- return (T) new StAXSource(this.inputFactory.createXMLStreamReader(reader));
+ return (T) new StAXSource(this.inputFactory.createXMLStreamReader(
+ this.fromResultSet ? this.owningResultSet.getCharacterStream(this.columnIndexOfXml) : new StringReader(this.stringRep)));
} catch (XMLStreamException ex) {
SQLException sqlEx = SQLError.createSQLException(ex.getMessage(), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, ex, this.exceptionInterceptor);
throw sqlEx;
@@ -259,6 +260,18 @@ public class MysqlSQLXML implements SQLX
}
}
+ private static void setFeature(Object factory, String name, boolean value) {
+ try {
+ if (factory instanceof DocumentBuilderFactory) {
+ ((DocumentBuilderFactory) factory).setFeature(name, value);
+ } else if (factory instanceof XMLReader) {
+ ((XMLReader) factory).setFeature(name, value);
+ }
+ } catch (Exception ignore) {
+ // no-op
+ }
+ }
+
@Override
public synchronized OutputStream setBinaryStream() throws SQLException {
checkClosed();
@@ -391,7 +404,7 @@ public class MysqlSQLXML implements SQLX
protected synchronized Reader serializeAsCharacterStream() throws SQLException {
checkClosed();
- if (this.workingWithResult) {
+ if (this.workingWithResult || this.owningResultSet == null) {
// figure out what kind of result
if (this.stringRep != null) {
return new StringReader(this.stringRep);