Skip to content

Commit

Permalink
Fix for MysqlSQLXML.
Browse files Browse the repository at this point in the history
  • Loading branch information
soklakov committed Jul 23, 2021
1 parent 1b8509a commit 4993d57
Showing 1 changed file with 46 additions and 33 deletions.
79 changes: 46 additions & 33 deletions src/main/user-impl/java/com/mysql/cj/jdbc/MysqlSQLXML.java
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -42,6 +42,7 @@
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;
Expand All @@ -65,7 +66,9 @@
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;
Expand Down Expand Up @@ -199,56 +202,54 @@ public <T extends Source> T getSource(Class<T> clazz) throws SQLException {

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, "");

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(), 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;
Expand All @@ -259,6 +260,18 @@ public <T extends Source> T getSource(Class<T> clazz) throws SQLException {
}
}

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();
Expand Down

0 comments on commit 4993d57

Please sign in to comment.