mirror of
https://github.com/stleary/JSON-java.git
synced 2025-08-03 03:15:32 -04:00
Resolving issue #743
- Recursive depth issue found in JSONObject - Recursive depth issue found in JSONArray
This commit is contained in:
parent
6dba7220e1
commit
6d811607dd
@ -149,11 +149,18 @@ public class JSONArray implements Iterable<Object> {
|
||||
* A Collection.
|
||||
*/
|
||||
public JSONArray(Collection<?> collection) {
|
||||
this(collection, 0);
|
||||
}
|
||||
|
||||
protected JSONArray(Collection<?> collection, int recursionDepth) {
|
||||
if (recursionDepth > JSONObject.RECURSION_DEPTH_LIMIT) {
|
||||
throw new JSONException("JSONArray has reached recursion depth limit of " + JSONObject.RECURSION_DEPTH_LIMIT);
|
||||
}
|
||||
if (collection == null) {
|
||||
this.myArrayList = new ArrayList<Object>();
|
||||
} else {
|
||||
this.myArrayList = new ArrayList<Object>(collection.size());
|
||||
this.addAll(collection, true);
|
||||
this.addAll(collection, true, recursionDepth);
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,7 +212,7 @@ public class JSONArray implements Iterable<Object> {
|
||||
throw new JSONException(
|
||||
"JSONArray initial value should be a string or collection or array.");
|
||||
}
|
||||
this.addAll(array, true);
|
||||
this.addAll(array, true, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1779,13 +1786,15 @@ public class JSONArray implements Iterable<Object> {
|
||||
* @param wrap
|
||||
* {@code true} to call {@link JSONObject#wrap(Object)} for each item,
|
||||
* {@code false} to add the items directly
|
||||
* @param recursionDepth
|
||||
* variable to keep the count of how nested the object creation is happening.
|
||||
*
|
||||
*/
|
||||
private void addAll(Collection<?> collection, boolean wrap) {
|
||||
private void addAll(Collection<?> collection, boolean wrap, int recursionDepth) {
|
||||
this.myArrayList.ensureCapacity(this.myArrayList.size() + collection.size());
|
||||
if (wrap) {
|
||||
for (Object o: collection){
|
||||
this.put(JSONObject.wrap(o));
|
||||
this.put(JSONObject.wrap(o, recursionDepth + 1));
|
||||
}
|
||||
} else {
|
||||
for (Object o: collection){
|
||||
@ -1815,6 +1824,10 @@ public class JSONArray implements Iterable<Object> {
|
||||
}
|
||||
}
|
||||
|
||||
private void addAll(Object array, boolean wrap) throws JSONException {
|
||||
this.addAll(array, wrap, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an array's elements to the JSONArray.
|
||||
*
|
||||
@ -1825,19 +1838,21 @@ public class JSONArray implements Iterable<Object> {
|
||||
* @param wrap
|
||||
* {@code true} to call {@link JSONObject#wrap(Object)} for each item,
|
||||
* {@code false} to add the items directly
|
||||
* @param recursionDepth
|
||||
* Variable to keep the count of how nested the object creation is happening.
|
||||
*
|
||||
* @throws JSONException
|
||||
* If not an array or if an array value is non-finite number.
|
||||
* @throws NullPointerException
|
||||
* Thrown if the array parameter is null.
|
||||
*/
|
||||
private void addAll(Object array, boolean wrap) throws JSONException {
|
||||
private void addAll(Object array, boolean wrap, int recursionDepth) throws JSONException {
|
||||
if (array.getClass().isArray()) {
|
||||
int length = Array.getLength(array);
|
||||
this.myArrayList.ensureCapacity(this.myArrayList.size() + length);
|
||||
if (wrap) {
|
||||
for (int i = 0; i < length; i += 1) {
|
||||
this.put(JSONObject.wrap(Array.get(array, i)));
|
||||
this.put(JSONObject.wrap(Array.get(array, i), recursionDepth + 1));
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < length; i += 1) {
|
||||
@ -1850,7 +1865,7 @@ public class JSONArray implements Iterable<Object> {
|
||||
// JSONArray
|
||||
this.myArrayList.addAll(((JSONArray)array).myArrayList);
|
||||
} else if (array instanceof Collection) {
|
||||
this.addAll((Collection<?>)array, wrap);
|
||||
this.addAll((Collection<?>)array, wrap, recursionDepth);
|
||||
} else if (array instanceof Iterable) {
|
||||
this.addAll((Iterable<?>)array, wrap);
|
||||
} else {
|
||||
|
@ -147,6 +147,7 @@ public class JSONObject {
|
||||
* The map where the JSONObject's properties are kept.
|
||||
*/
|
||||
private final Map<String, Object> map;
|
||||
public static final int RECURSION_DEPTH_LIMIT = 1000;
|
||||
|
||||
public Class<? extends Map> getMapType() {
|
||||
return map.getClass();
|
||||
@ -276,6 +277,17 @@ public class JSONObject {
|
||||
* If a key in the map is <code>null</code>
|
||||
*/
|
||||
public JSONObject(Map<?, ?> m) {
|
||||
this(m, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a JSONObject from a map with recursion depth.
|
||||
*
|
||||
*/
|
||||
protected JSONObject(Map<?, ?> m, int recursionDepth) {
|
||||
if (recursionDepth > RECURSION_DEPTH_LIMIT) {
|
||||
throw new JSONException("JSONObject has reached recursion depth limit of " + RECURSION_DEPTH_LIMIT);
|
||||
}
|
||||
if (m == null) {
|
||||
this.map = new HashMap<String, Object>();
|
||||
} else {
|
||||
@ -287,7 +299,7 @@ public class JSONObject {
|
||||
final Object value = e.getValue();
|
||||
if (value != null) {
|
||||
testValidity(value);
|
||||
this.map.put(String.valueOf(e.getKey()), wrap(value));
|
||||
this.map.put(String.valueOf(e.getKey()), wrap(value, recursionDepth + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2566,7 +2578,15 @@ public class JSONObject {
|
||||
return wrap(object, null);
|
||||
}
|
||||
|
||||
public static Object wrap(Object object, int recursionDepth) {
|
||||
return wrap(object, null, recursionDepth);
|
||||
}
|
||||
|
||||
private static Object wrap(Object object, Set<Object> objectsRecord) {
|
||||
return wrap(object, objectsRecord, 0);
|
||||
}
|
||||
|
||||
private static Object wrap(Object object, Set<Object> objectsRecord, int recursionDepth) {
|
||||
try {
|
||||
if (NULL.equals(object)) {
|
||||
return NULL;
|
||||
@ -2584,14 +2604,14 @@ public class JSONObject {
|
||||
|
||||
if (object instanceof Collection) {
|
||||
Collection<?> coll = (Collection<?>) object;
|
||||
return new JSONArray(coll);
|
||||
return new JSONArray(coll, recursionDepth);
|
||||
}
|
||||
if (object.getClass().isArray()) {
|
||||
return new JSONArray(object);
|
||||
}
|
||||
if (object instanceof Map) {
|
||||
Map<?, ?> map = (Map<?, ?>) object;
|
||||
return new JSONObject(map);
|
||||
return new JSONObject(map, recursionDepth);
|
||||
}
|
||||
Package objectPackage = object.getClass().getPackage();
|
||||
String objectPackageName = objectPackage != null ? objectPackage
|
||||
|
@ -1417,4 +1417,25 @@ public class JSONArrayTest {
|
||||
.put(2);
|
||||
assertFalse(ja1.similar(ja3));
|
||||
}
|
||||
|
||||
@Test(expected = JSONException.class)
|
||||
public void testRecursiveDepth() {
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
map.put("t", map);
|
||||
new JSONArray().put(map);
|
||||
}
|
||||
|
||||
@Test(expected = JSONException.class)
|
||||
public void testRecursiveDepthAtPosition() {
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
map.put("t", map);
|
||||
new JSONArray().put(0, map);
|
||||
}
|
||||
|
||||
@Test(expected = JSONException.class)
|
||||
public void testRecursiveDepthArray() {
|
||||
ArrayList<Object> array = new ArrayList<>();
|
||||
array.add(array);
|
||||
new JSONArray(array);
|
||||
}
|
||||
}
|
||||
|
@ -3718,4 +3718,21 @@ public class JSONObjectTest {
|
||||
assertThrows(JSONException.class, () -> new JSONObject(bean));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = JSONException.class)
|
||||
public void issue743SerializationMap() {
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
map.put("t", map);
|
||||
JSONObject object = new JSONObject(map);
|
||||
String jsonString = object.toString();
|
||||
}
|
||||
|
||||
@Test(expected = JSONException.class)
|
||||
public void testCircularReferenceMultipleLevel() {
|
||||
HashMap<String, Object> inside = new HashMap<>();
|
||||
HashMap<String, Object> jsonObject = new HashMap<>();
|
||||
inside.put("inside", jsonObject);
|
||||
jsonObject.put("test", inside);
|
||||
new JSONObject(jsonObject);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user