[#2233] Turn off some XML features for security reasons
This commit is contained in:
parent
80d8642c5b
commit
ad1f015401
@ -89,6 +89,7 @@ import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
|
||||
@ -1467,6 +1468,33 @@ public class DefaultDSLContext extends AbstractScope implements DSLContext, Seri
|
||||
public Result<Record> fetchFromXML(String string) {
|
||||
try {
|
||||
SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// [JOOX #136] FIX START: Prevent OWASP attack vectors
|
||||
try {
|
||||
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
}
|
||||
catch (ParserConfigurationException ignore) {}
|
||||
|
||||
try {
|
||||
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
||||
}
|
||||
catch (ParserConfigurationException ignore) {}
|
||||
|
||||
try {
|
||||
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
||||
}
|
||||
catch (ParserConfigurationException ignore) {}
|
||||
|
||||
// [#149] Not implemented on Android
|
||||
try {
|
||||
factory.setXIncludeAware(false);
|
||||
}
|
||||
catch (UnsupportedOperationException ignore) {}
|
||||
|
||||
// [JOOX #136] FIX END
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
SAXParser saxParser = factory.newSAXParser();
|
||||
// TODO: Why does the SAXParser replace \r by \n?
|
||||
|
||||
|
||||
171
jOOQ/src/main/java/org/jooq/impl/XMLHandler.java
Normal file
171
jOOQ/src/main/java/org/jooq/impl/XMLHandler.java
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Other licenses:
|
||||
* -----------------------------------------------------------------------------
|
||||
* Commercial licenses for this work are available. These replace the above
|
||||
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
|
||||
* database integrations.
|
||||
*
|
||||
* For more information, please visit: http://www.jooq.org/licenses
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
package org.jooq.impl;
|
||||
|
||||
import static org.jooq.impl.DSL.field;
|
||||
import static org.jooq.impl.DSL.name;
|
||||
import static org.jooq.impl.DefaultDataType.getDataType;
|
||||
import static org.jooq.impl.SQLDataType.VARCHAR;
|
||||
import static org.jooq.impl.Tools.EMPTY_FIELD;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.Result;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
final class XMLHandler extends DefaultHandler {
|
||||
|
||||
private final DSLContext ctx;
|
||||
private boolean inResult;
|
||||
private boolean inFields;
|
||||
private boolean inRecords;
|
||||
private int inRecord;
|
||||
Result<Record> result;
|
||||
private Field<?>[] fieldsArray;
|
||||
private final List<Field<?>> fields;
|
||||
private final List<String> values;
|
||||
private int column;
|
||||
|
||||
XMLHandler(DSLContext ctx) {
|
||||
this.ctx = ctx;
|
||||
this.fields = new ArrayList<Field<?>>();
|
||||
this.values = new ArrayList<String>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||
if (!inResult && "result".equals(qName)) {
|
||||
inResult = true;
|
||||
}
|
||||
else if (inResult && "fields".equals(qName)) {
|
||||
inFields = true;
|
||||
}
|
||||
else if (inResult && inFields && "field".equals(qName)) {
|
||||
String catalog = attributes.getValue("catalog");
|
||||
String schema = attributes.getValue("schema");
|
||||
String table = attributes.getValue("table");
|
||||
String name = attributes.getValue("name");
|
||||
String type = attributes.getValue("type");
|
||||
|
||||
fields.add(field(name(catalog, schema, table, name), getDataType(ctx.dialect(), type)));
|
||||
}
|
||||
else if (inResult && "records".equals(qName)) {
|
||||
inRecords = true;
|
||||
}
|
||||
else if (inResult && "record".equals(qName)) {
|
||||
inRecord++;
|
||||
column = 0;
|
||||
}
|
||||
else if (result == null) {
|
||||
String fieldName;
|
||||
|
||||
if (("value").equals(qName) && (fieldName = attributes.getValue("field")) != null)
|
||||
fields.add(field(name(fieldName), VARCHAR));
|
||||
else
|
||||
fields.add(field(name(qName), VARCHAR));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void endElement(String uri, String localName, String qName) throws SAXException {
|
||||
if (inResult && inRecord == 0 && "result".equals(qName)) {
|
||||
inResult = false;
|
||||
}
|
||||
else if (inResult && inFields && "fields".equals(qName)) {
|
||||
inFields = false;
|
||||
initResult();
|
||||
}
|
||||
else if (inResult && "records".equals(qName)) {
|
||||
inRecords = false;
|
||||
}
|
||||
else if (inRecord > 0 && "record".equals(qName)) {
|
||||
inRecord--;
|
||||
|
||||
initResult();
|
||||
Record r = ctx.newRecord(fieldsArray);
|
||||
r.from(values);
|
||||
result.add(r);
|
||||
|
||||
values.clear();
|
||||
}
|
||||
else {
|
||||
column++;
|
||||
}
|
||||
}
|
||||
|
||||
private void initResult() {
|
||||
if (result == null)
|
||||
|
||||
// Parsing RecordFormat.VALUE_ELEMENTS format
|
||||
if (onlyValueFields(fields))
|
||||
result = ctx.newResult(fieldsArray = Tools.fields(fields.size()));
|
||||
else
|
||||
result = ctx.newResult(fieldsArray = fields.toArray(EMPTY_FIELD));
|
||||
}
|
||||
|
||||
private static boolean onlyValueFields(List<Field<?>> fields) {
|
||||
if (fields.size() <= 1)
|
||||
return false;
|
||||
|
||||
for (Field<?> field : fields)
|
||||
if (!"value".equals(field.getName()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void characters(char[] ch, int start, int length) throws SAXException {
|
||||
String value = new String(ch, start, length);
|
||||
|
||||
if (values.size() == column)
|
||||
values.add(value);
|
||||
else
|
||||
values.set(column, values.get(column) + value);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user