mirror of
https://github.com/stleary/JSON-java.git
synced 2026-01-25 00:00:38 -05:00
fix: limit the nesting depth in JSONML
Limit the XML nesting depth for CVE-2022-45688 when using the JsonML transform.
This commit is contained in:
@@ -27,7 +27,32 @@ public class JSONML {
|
||||
XMLTokener x,
|
||||
boolean arrayForm,
|
||||
JSONArray ja,
|
||||
boolean keepStrings
|
||||
boolean keepStrings,
|
||||
int currentNestingDepth
|
||||
) throws JSONException {
|
||||
return parse(x,arrayForm, ja,
|
||||
keepStrings ? XMLtoJSONMLParserConfiguration.KEEP_STRINGS : XMLtoJSONMLParserConfiguration.ORIGINAL,
|
||||
currentNestingDepth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse XML values and store them in a JSONArray.
|
||||
* @param x The XMLTokener containing the source string.
|
||||
* @param arrayForm true if array form, false if object form.
|
||||
* @param ja The JSONArray that is containing the current tag or null
|
||||
* if we are at the outermost level.
|
||||
* @param config The XML parser configuration:
|
||||
* XMLtoJSONMLParserConfiguration.ORIGINAL is the default behaviour;
|
||||
* XMLtoJSONMLParserConfiguration.KEEP_STRINGS means Don't type-convert text nodes and attribute values.
|
||||
* @return A JSONArray if the value is the outermost tag, otherwise null.
|
||||
* @throws JSONException if a parsing error occurs
|
||||
*/
|
||||
private static Object parse(
|
||||
XMLTokener x,
|
||||
boolean arrayForm,
|
||||
JSONArray ja,
|
||||
XMLtoJSONMLParserConfiguration config,
|
||||
int currentNestingDepth
|
||||
) throws JSONException {
|
||||
String attribute;
|
||||
char c;
|
||||
@@ -152,7 +177,7 @@ public class JSONML {
|
||||
if (!(token instanceof String)) {
|
||||
throw x.syntaxError("Missing value");
|
||||
}
|
||||
newjo.accumulate(attribute, keepStrings ? ((String)token) :XML.stringToValue((String)token));
|
||||
newjo.accumulate(attribute, config.isKeepStrings() ? ((String)token) :XML.stringToValue((String)token));
|
||||
token = null;
|
||||
} else {
|
||||
newjo.accumulate(attribute, "");
|
||||
@@ -181,7 +206,12 @@ public class JSONML {
|
||||
if (token != XML.GT) {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
closeTag = (String)parse(x, arrayForm, newja, keepStrings);
|
||||
|
||||
if (currentNestingDepth == config.getMaxNestingDepth()) {
|
||||
throw x.syntaxError("Maximum nesting depth of " + config.getMaxNestingDepth() + " reached");
|
||||
}
|
||||
|
||||
closeTag = (String)parse(x, arrayForm, newja, config, currentNestingDepth + 1);
|
||||
if (closeTag != null) {
|
||||
if (!closeTag.equals(tagName)) {
|
||||
throw x.syntaxError("Mismatched '" + tagName +
|
||||
@@ -203,7 +233,7 @@ public class JSONML {
|
||||
} else {
|
||||
if (ja != null) {
|
||||
ja.put(token instanceof String
|
||||
? keepStrings ? XML.unescape((String)token) :XML.stringToValue((String)token)
|
||||
? (config.isKeepStrings() ? XML.unescape((String)token) : XML.stringToValue((String)token))
|
||||
: token);
|
||||
}
|
||||
}
|
||||
@@ -224,7 +254,7 @@ public class JSONML {
|
||||
* @throws JSONException Thrown on error converting to a JSONArray
|
||||
*/
|
||||
public static JSONArray toJSONArray(String string) throws JSONException {
|
||||
return (JSONArray)parse(new XMLTokener(string), true, null, false);
|
||||
return (JSONArray)parse(new XMLTokener(string), true, null, XMLtoJSONMLParserConfiguration.ORIGINAL, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -235,8 +265,8 @@ public class JSONML {
|
||||
* attributes, then the second element will be JSONObject containing the
|
||||
* name/value pairs. If the tag contains children, then strings and
|
||||
* JSONArrays will represent the child tags.
|
||||
* As opposed to toJSONArray this method does not attempt to convert
|
||||
* any text node or attribute value to any type
|
||||
* As opposed to toJSONArray this method does not attempt to convert
|
||||
* any text node or attribute value to any type
|
||||
* but just leaves it as a string.
|
||||
* Comments, prologs, DTDs, and <pre>{@code <[ [ ]]>}</pre> are ignored.
|
||||
* @param string The source string.
|
||||
@@ -246,7 +276,7 @@ public class JSONML {
|
||||
* @throws JSONException Thrown on error converting to a JSONArray
|
||||
*/
|
||||
public static JSONArray toJSONArray(String string, boolean keepStrings) throws JSONException {
|
||||
return (JSONArray)parse(new XMLTokener(string), true, null, keepStrings);
|
||||
return (JSONArray)parse(new XMLTokener(string), true, null, keepStrings, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -257,8 +287,8 @@ public class JSONML {
|
||||
* attributes, then the second element will be JSONObject containing the
|
||||
* name/value pairs. If the tag contains children, then strings and
|
||||
* JSONArrays will represent the child content and tags.
|
||||
* As opposed to toJSONArray this method does not attempt to convert
|
||||
* any text node or attribute value to any type
|
||||
* As opposed to toJSONArray this method does not attempt to convert
|
||||
* any text node or attribute value to any type
|
||||
* but just leaves it as a string.
|
||||
* Comments, prologs, DTDs, and <pre>{@code <[ [ ]]>}</pre> are ignored.
|
||||
* @param x An XMLTokener.
|
||||
@@ -268,7 +298,7 @@ public class JSONML {
|
||||
* @throws JSONException Thrown on error converting to a JSONArray
|
||||
*/
|
||||
public static JSONArray toJSONArray(XMLTokener x, boolean keepStrings) throws JSONException {
|
||||
return (JSONArray)parse(x, true, null, keepStrings);
|
||||
return (JSONArray)parse(x, true, null, keepStrings, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -285,7 +315,7 @@ public class JSONML {
|
||||
* @throws JSONException Thrown on error converting to a JSONArray
|
||||
*/
|
||||
public static JSONArray toJSONArray(XMLTokener x) throws JSONException {
|
||||
return (JSONArray)parse(x, true, null, false);
|
||||
return (JSONArray)parse(x, true, null, false, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -303,10 +333,10 @@ public class JSONML {
|
||||
* @throws JSONException Thrown on error converting to a JSONObject
|
||||
*/
|
||||
public static JSONObject toJSONObject(String string) throws JSONException {
|
||||
return (JSONObject)parse(new XMLTokener(string), false, null, false);
|
||||
return (JSONObject)parse(new XMLTokener(string), false, null, false, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONObject using the JsonML transform. Each XML tag is represented as
|
||||
@@ -323,10 +353,32 @@ public class JSONML {
|
||||
* @throws JSONException Thrown on error converting to a JSONObject
|
||||
*/
|
||||
public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException {
|
||||
return (JSONObject)parse(new XMLTokener(string), false, null, keepStrings);
|
||||
return (JSONObject)parse(new XMLTokener(string), false, null, keepStrings, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONObject using the JsonML transform. Each XML tag is represented as
|
||||
* a JSONObject with a "tagName" property. If the tag has attributes, then
|
||||
* the attributes will be in the JSONObject as properties. If the tag
|
||||
* contains children, the object will have a "childNodes" property which
|
||||
* will be an array of strings and JsonML JSONObjects.
|
||||
|
||||
* Comments, prologs, DTDs, and <pre>{@code <[ [ ]]>}</pre> are ignored.
|
||||
* @param string The XML source text.
|
||||
* @param config The XML parser configuration:
|
||||
* XMLtoJSONMLParserConfiguration.ORIGINAL is the default behaviour;
|
||||
* XMLtoJSONMLParserConfiguration.KEEP_STRINGS means values will not be coerced into boolean
|
||||
* or numeric values and will instead be left as strings
|
||||
* @return A JSONObject containing the structured data from the XML string.
|
||||
* @throws JSONException Thrown on error converting to a JSONObject
|
||||
*/
|
||||
public static JSONObject toJSONObject(String string, XMLtoJSONMLParserConfiguration config) throws JSONException {
|
||||
return (JSONObject)parse(new XMLTokener(string), false, null, config, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONObject using the JsonML transform. Each XML tag is represented as
|
||||
@@ -341,7 +393,7 @@ public class JSONML {
|
||||
* @throws JSONException Thrown on error converting to a JSONObject
|
||||
*/
|
||||
public static JSONObject toJSONObject(XMLTokener x) throws JSONException {
|
||||
return (JSONObject)parse(x, false, null, false);
|
||||
return (JSONObject)parse(x, false, null, false, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -361,7 +413,29 @@ public class JSONML {
|
||||
* @throws JSONException Thrown on error converting to a JSONObject
|
||||
*/
|
||||
public static JSONObject toJSONObject(XMLTokener x, boolean keepStrings) throws JSONException {
|
||||
return (JSONObject)parse(x, false, null, keepStrings);
|
||||
return (JSONObject)parse(x, false, null, keepStrings, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONObject using the JsonML transform. Each XML tag is represented as
|
||||
* a JSONObject with a "tagName" property. If the tag has attributes, then
|
||||
* the attributes will be in the JSONObject as properties. If the tag
|
||||
* contains children, the object will have a "childNodes" property which
|
||||
* will be an array of strings and JsonML JSONObjects.
|
||||
|
||||
* Comments, prologs, DTDs, and <pre>{@code <[ [ ]]>}</pre> are ignored.
|
||||
* @param x An XMLTokener of the XML source text.
|
||||
* @param config The XML parser configuration:
|
||||
* XMLtoJSONMLParserConfiguration.ORIGINAL is the default behaviour;
|
||||
* XMLtoJSONMLParserConfiguration.KEEP_STRINGS means values will not be coerced into boolean
|
||||
* or numeric values and will instead be left as strings
|
||||
* @return A JSONObject containing the structured data from the XML string.
|
||||
* @throws JSONException Thrown on error converting to a JSONObject
|
||||
*/
|
||||
public static JSONObject toJSONObject(XMLTokener x, XMLtoJSONMLParserConfiguration config) throws JSONException {
|
||||
return (JSONObject)parse(x, false, null, config, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -442,6 +516,7 @@ public class JSONML {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reverse the JSONML transformation, making an XML text from a JSONObject.
|
||||
* The JSONObject must contain a "tagName" property. If it has children,
|
||||
|
||||
Reference in New Issue
Block a user