mirror of
https://github.com/stleary/JSON-java.git
synced 2025-08-03 03:15:32 -04:00
fix: limit the nesting depth
This commit is contained in:
parent
5920eca2d7
commit
f566a1d9ee
@ -232,7 +232,7 @@ public class XML {
|
|||||||
* @return true if the close tag is processed.
|
* @return true if the close tag is processed.
|
||||||
* @throws JSONException
|
* @throws JSONException
|
||||||
*/
|
*/
|
||||||
private static boolean parse(XMLTokener x, JSONObject context, String name, XMLParserConfiguration config)
|
private static boolean parse(XMLTokener x, JSONObject context, String name, XMLParserConfiguration config, int currentNestingDepth)
|
||||||
throws JSONException {
|
throws JSONException {
|
||||||
char c;
|
char c;
|
||||||
int i;
|
int i;
|
||||||
@ -402,7 +402,11 @@ public class XML {
|
|||||||
|
|
||||||
} else if (token == LT) {
|
} else if (token == LT) {
|
||||||
// Nested element
|
// Nested element
|
||||||
if (parse(x, jsonObject, tagName, config)) {
|
if (currentNestingDepth == config.getMaxNestingDepth()) {
|
||||||
|
throw x.syntaxError("Maximum nesting depth of " + config.getMaxNestingDepth() + " reached");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parse(x, jsonObject, tagName, config, currentNestingDepth + 1)) {
|
||||||
if (config.getForceList().contains(tagName)) {
|
if (config.getForceList().contains(tagName)) {
|
||||||
// Force the value to be an array
|
// Force the value to be an array
|
||||||
if (jsonObject.length() == 0) {
|
if (jsonObject.length() == 0) {
|
||||||
@ -644,6 +648,10 @@ public class XML {
|
|||||||
* All values are converted as strings, for 1, 01, 29.0 will not be coerced to
|
* All values are converted as strings, for 1, 01, 29.0 will not be coerced to
|
||||||
* numbers but will instead be the exact value as seen in the XML document.
|
* numbers but will instead be the exact value as seen in the XML document.
|
||||||
*
|
*
|
||||||
|
* This method can parse documents with a maximum nesting depth of 256. If you
|
||||||
|
* need to parse documents with a nesting depth greater than 256, you should use
|
||||||
|
*
|
||||||
|
*
|
||||||
* @param reader The XML source reader.
|
* @param reader The XML source reader.
|
||||||
* @param config Configuration options for the parser
|
* @param config Configuration options for the parser
|
||||||
* @return A JSONObject containing the structured data from the XML string.
|
* @return A JSONObject containing the structured data from the XML string.
|
||||||
@ -655,7 +663,7 @@ public class XML {
|
|||||||
while (x.more()) {
|
while (x.more()) {
|
||||||
x.skipPast("<");
|
x.skipPast("<");
|
||||||
if(x.more()) {
|
if(x.more()) {
|
||||||
parse(x, jo, null, config);
|
parse(x, jo, null, config, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return jo;
|
return jo;
|
||||||
|
@ -16,6 +16,12 @@ import java.util.Set;
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings({""})
|
@SuppressWarnings({""})
|
||||||
public class XMLParserConfiguration {
|
public class XMLParserConfiguration {
|
||||||
|
/**
|
||||||
|
* Used to indicate there's no defined limit to the maximum nesting depth when parsing a XML
|
||||||
|
* document to JSON.
|
||||||
|
*/
|
||||||
|
public static final int UNDEFINED_MAXIMUM_NESTING_DEPTH = -1;
|
||||||
|
|
||||||
/** Original Configuration of the XML Parser. */
|
/** Original Configuration of the XML Parser. */
|
||||||
public static final XMLParserConfiguration ORIGINAL
|
public static final XMLParserConfiguration ORIGINAL
|
||||||
= new XMLParserConfiguration();
|
= new XMLParserConfiguration();
|
||||||
@ -54,6 +60,12 @@ public class XMLParserConfiguration {
|
|||||||
*/
|
*/
|
||||||
private Set<String> forceList;
|
private Set<String> forceList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When parsing the XML into JSON, specifies the tags whose values should be converted
|
||||||
|
* to arrays
|
||||||
|
*/
|
||||||
|
private int maxNestingDepth = UNDEFINED_MAXIMUM_NESTING_DEPTH;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default parser configuration. Does not keep strings (tries to implicitly convert
|
* Default parser configuration. Does not keep strings (tries to implicitly convert
|
||||||
* values), and the CDATA Tag Name is "content".
|
* values), and the CDATA Tag Name is "content".
|
||||||
@ -297,4 +309,33 @@ public class XMLParserConfiguration {
|
|||||||
newConfig.forceList = Collections.unmodifiableSet(cloneForceList);
|
newConfig.forceList = Collections.unmodifiableSet(cloneForceList);
|
||||||
return newConfig;
|
return newConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum nesting depth that the parser will descend before throwing an exception
|
||||||
|
* when parsing the XML into JSON.
|
||||||
|
* @return the maximum nesting depth set for this configuration
|
||||||
|
*/
|
||||||
|
public int getMaxNestingDepth() {
|
||||||
|
return maxNestingDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the maximum nesting depth that the parser will descend before throwing an exception
|
||||||
|
* when parsing the XML into JSON. The default max nesting depth is undefined, which means the
|
||||||
|
* parser will go as deep as the maximum call stack size allows. Using any negative value as a
|
||||||
|
* parameter is equivalent to setting no limit to the nesting depth.
|
||||||
|
* @param maxNestingDepth the maximum nesting depth allowed to the XML parser
|
||||||
|
* @return The existing configuration will not be modified. A new configuration is returned.
|
||||||
|
*/
|
||||||
|
public XMLParserConfiguration withMaxNestingDepth(int maxNestingDepth) {
|
||||||
|
XMLParserConfiguration newConfig = this.clone();
|
||||||
|
|
||||||
|
if (maxNestingDepth > UNDEFINED_MAXIMUM_NESTING_DEPTH) {
|
||||||
|
newConfig.maxNestingDepth = maxNestingDepth;
|
||||||
|
} else {
|
||||||
|
newConfig.maxNestingDepth = UNDEFINED_MAXIMUM_NESTING_DEPTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newConfig;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1052,6 +1052,29 @@ public class XMLConfigurationTest {
|
|||||||
Util.compareActualVsExpectedJsonObjects(jsonObject, expetedJsonObject);
|
Util.compareActualVsExpectedJsonObjects(jsonObject, expetedJsonObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMaxNestingDepthIsSet() {
|
||||||
|
XMLParserConfiguration xmlParserConfiguration = XMLParserConfiguration.ORIGINAL;
|
||||||
|
|
||||||
|
assertEquals(xmlParserConfiguration.getMaxNestingDepth(), XMLParserConfiguration.UNDEFINED_MAXIMUM_NESTING_DEPTH);
|
||||||
|
|
||||||
|
xmlParserConfiguration = xmlParserConfiguration.withMaxNestingDepth(42);
|
||||||
|
|
||||||
|
assertEquals(xmlParserConfiguration.getMaxNestingDepth(), 42);
|
||||||
|
|
||||||
|
xmlParserConfiguration = xmlParserConfiguration.withMaxNestingDepth(0);
|
||||||
|
|
||||||
|
assertEquals(xmlParserConfiguration.getMaxNestingDepth(), 0);
|
||||||
|
|
||||||
|
xmlParserConfiguration = xmlParserConfiguration.withMaxNestingDepth(-31415926);
|
||||||
|
|
||||||
|
assertEquals(xmlParserConfiguration.getMaxNestingDepth(), XMLParserConfiguration.UNDEFINED_MAXIMUM_NESTING_DEPTH);
|
||||||
|
|
||||||
|
xmlParserConfiguration = xmlParserConfiguration.withMaxNestingDepth(Integer.MIN_VALUE);
|
||||||
|
|
||||||
|
assertEquals(xmlParserConfiguration.getMaxNestingDepth(), XMLParserConfiguration.UNDEFINED_MAXIMUM_NESTING_DEPTH);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method, given an input string and expected result,
|
* Convenience method, given an input string and expected result,
|
||||||
* convert to JSONObject and compare actual to expected result.
|
* convert to JSONObject and compare actual to expected result.
|
||||||
|
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user