File mysql-connector-java-CVE-2021-2471.patch of Package mysql-connector-java.23087
Index: mysql-connector-java-5.1.47/src/com/mysql/jdbc/JDBC4MysqlSQLXML.java
===================================================================
--- mysql-connector-java-5.1.47.orig/src/com/mysql/jdbc/JDBC4MysqlSQLXML.java
+++ mysql-connector-java-5.1.47/src/com/mysql/jdbc/JDBC4MysqlSQLXML.java
@@ -39,6 +39,7 @@ import java.sql.SQLXML;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
+import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
@@ -66,6 +67,11 @@ import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+import com.mysql.jdbc.MysqlErrorNumbers;
+
public class JDBC4MysqlSQLXML implements SQLXML {
@@ -280,31 +286,41 @@ public class JDBC4MysqlSQLXML implements
// (futureproofing)
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));
- }
-
- return (T) new SAXSource(inputSource);
+ 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;
+ }
} 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, "");
- return (T) new DOMSource(builder.parse(inputSource));
+ DocumentBuilder builder = builderFactory.newDocumentBuilder();
+
+ 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(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor);
sqlEx.initCause(t);
@@ -313,26 +329,11 @@ public class JDBC4MysqlSQLXML implements
}
} 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(reader);
+ return (T) new StreamSource(this.fromResultSet ? this.owningResultSet.getCharacterStream(this.columnIndexOfXml) : new StringReader(this.stringRep));
} 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(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor);
sqlEx.initCause(ex);
@@ -345,6 +346,18 @@ public class JDBC4MysqlSQLXML implements
}
}
+ 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
+ }
+ }
+
/**
* Retrieves a stream that can be used to write the XML value that this
* SQLXML instance represents. The stream begins at position 0. The bytes of
@@ -562,7 +575,7 @@ public class JDBC4MysqlSQLXML implements
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);
Index: mysql-connector-java-5.1.47/src/com/mysql/jdbc/MysqlErrorNumbers.java
===================================================================
--- mysql-connector-java-5.1.47.orig/src/com/mysql/jdbc/MysqlErrorNumbers.java
+++ mysql-connector-java-5.1.47/src/com/mysql/jdbc/MysqlErrorNumbers.java
@@ -947,6 +947,8 @@ public final class MysqlErrorNumbers {
public static final int ERROR_CODE_NULL_LOAD_BALANCED_CONNECTION = 1000001;
public static final int ERROR_CODE_REPLICATION_CONNECTION_WITH_NO_HOSTS = 1000002;
+ public static final String SQL_STATE_ILLEGAL_ARGUMENT = "S1009";
+
private MysqlErrorNumbers() {
// prevent instantiation
}