Skip to content

Commit 4993d57

Browse files
committed
Fix for MysqlSQLXML.
1 parent 1b8509a commit 4993d57

File tree

1 file changed

+46
-33
lines changed

1 file changed

+46
-33
lines changed

src/main/user-impl/java/com/mysql/cj/jdbc/MysqlSQLXML.java

Lines changed: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2002, 2020, Oracle and/or its affiliates.
2+
* Copyright (c) 2002, 2021, Oracle and/or its affiliates.
33
*
44
* This program is free software; you can redistribute it and/or modify it under
55
* the terms of the GNU General Public License, version 2.0, as published by the
@@ -42,6 +42,7 @@
4242
import java.sql.SQLException;
4343
import java.sql.SQLXML;
4444

45+
import javax.xml.XMLConstants;
4546
import javax.xml.parsers.DocumentBuilder;
4647
import javax.xml.parsers.DocumentBuilderFactory;
4748
import javax.xml.stream.XMLInputFactory;
@@ -65,7 +66,9 @@
6566
import org.xml.sax.Attributes;
6667
import org.xml.sax.InputSource;
6768
import org.xml.sax.SAXException;
69+
import org.xml.sax.XMLReader;
6870
import org.xml.sax.helpers.DefaultHandler;
71+
import org.xml.sax.helpers.XMLReaderFactory;
6972

7073
import com.mysql.cj.Messages;
7174
import com.mysql.cj.exceptions.ExceptionInterceptor;
@@ -199,56 +202,54 @@ public <T extends Source> T getSource(Class<T> clazz) throws SQLException {
199202

200203
if (clazz == null || clazz.equals(SAXSource.class)) {
201204

202-
InputSource inputSource = null;
203-
204-
if (this.fromResultSet) {
205-
inputSource = new InputSource(this.owningResultSet.getCharacterStream(this.columnIndexOfXml));
206-
} else {
207-
inputSource = new InputSource(new StringReader(this.stringRep));
205+
try {
206+
XMLReader reader = XMLReaderFactory.createXMLReader();
207+
// According to https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html
208+
reader.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
209+
setFeature(reader, "http://apache.org/xml/features/disallow-doctype-decl", true);
210+
setFeature(reader, "http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
211+
setFeature(reader, "http://xml.org/sax/features/external-general-entities", false);
212+
setFeature(reader, "http://xml.org/sax/features/external-parameter-entities", false);
213+
214+
return (T) new SAXSource(reader, this.fromResultSet ? new InputSource(this.owningResultSet.getCharacterStream(this.columnIndexOfXml))
215+
: new InputSource(new StringReader(this.stringRep)));
216+
} catch (SAXException ex) {
217+
SQLException sqlEx = SQLError.createSQLException(ex.getMessage(), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, ex, this.exceptionInterceptor);
218+
throw sqlEx;
208219
}
209220

210-
return (T) new SAXSource(inputSource);
211221
} else if (clazz.equals(DOMSource.class)) {
212222
try {
213223
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
214224
builderFactory.setNamespaceAware(true);
215-
DocumentBuilder builder = builderFactory.newDocumentBuilder();
216225

217-
InputSource inputSource = null;
226+
// According to https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html
227+
setFeature(builderFactory, XMLConstants.FEATURE_SECURE_PROCESSING, true);
228+
setFeature(builderFactory, "http://apache.org/xml/features/disallow-doctype-decl", true);
229+
setFeature(builderFactory, "http://xml.org/sax/features/external-general-entities", false);
230+
setFeature(builderFactory, "http://xml.org/sax/features/external-parameter-entities", false);
231+
setFeature(builderFactory, "http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
232+
builderFactory.setXIncludeAware(false);
233+
builderFactory.setExpandEntityReferences(false);
218234

219-
if (this.fromResultSet) {
220-
inputSource = new InputSource(this.owningResultSet.getCharacterStream(this.columnIndexOfXml));
221-
} else {
222-
inputSource = new InputSource(new StringReader(this.stringRep));
223-
}
235+
builderFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
224236

225-
return (T) new DOMSource(builder.parse(inputSource));
237+
DocumentBuilder builder = builderFactory.newDocumentBuilder();
238+
239+
return (T) new DOMSource(builder.parse(this.fromResultSet ? new InputSource(this.owningResultSet.getCharacterStream(this.columnIndexOfXml))
240+
: new InputSource(new StringReader(this.stringRep))));
226241
} catch (Throwable t) {
227242
SQLException sqlEx = SQLError.createSQLException(t.getMessage(), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, t, this.exceptionInterceptor);
228243
throw sqlEx;
229244
}
230245

231246
} else if (clazz.equals(StreamSource.class)) {
232-
Reader reader = null;
233-
234-
if (this.fromResultSet) {
235-
reader = this.owningResultSet.getCharacterStream(this.columnIndexOfXml);
236-
} else {
237-
reader = new StringReader(this.stringRep);
238-
}
247+
return (T) new StreamSource(this.fromResultSet ? this.owningResultSet.getCharacterStream(this.columnIndexOfXml) : new StringReader(this.stringRep));
239248

240-
return (T) new StreamSource(reader);
241249
} else if (clazz.equals(StAXSource.class)) {
242250
try {
243-
Reader reader = null;
244-
245-
if (this.fromResultSet) {
246-
reader = this.owningResultSet.getCharacterStream(this.columnIndexOfXml);
247-
} else {
248-
reader = new StringReader(this.stringRep);
249-
}
250-
251-
return (T) new StAXSource(this.inputFactory.createXMLStreamReader(reader));
251+
return (T) new StAXSource(this.inputFactory.createXMLStreamReader(
252+
this.fromResultSet ? this.owningResultSet.getCharacterStream(this.columnIndexOfXml) : new StringReader(this.stringRep)));
252253
} catch (XMLStreamException ex) {
253254
SQLException sqlEx = SQLError.createSQLException(ex.getMessage(), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, ex, this.exceptionInterceptor);
254255
throw sqlEx;
@@ -259,6 +260,18 @@ public <T extends Source> T getSource(Class<T> clazz) throws SQLException {
259260
}
260261
}
261262

263+
private static void setFeature(Object factory, String name, boolean value) {
264+
try {
265+
if (factory instanceof DocumentBuilderFactory) {
266+
((DocumentBuilderFactory) factory).setFeature(name, value);
267+
} else if (factory instanceof XMLReader) {
268+
((XMLReader) factory).setFeature(name, value);
269+
}
270+
} catch (Exception ignore) {
271+
// no-op
272+
}
273+
}
274+
262275
@Override
263276
public synchronized OutputStream setBinaryStream() throws SQLException {
264277
checkClosed();

0 commit comments

Comments
 (0)