Skip to content

Commit

Permalink
fixes #193: Guard against stack overflow
Browse files Browse the repository at this point in the history
This adds a quick and dirty guard against a stack overflow condition when deserializing severely nested data.
  • Loading branch information
guusdk committed Jul 2, 2024
1 parent e00ef31 commit e3a22fa
Showing 1 changed file with 25 additions and 0 deletions.
25 changes: 25 additions & 0 deletions genson/src/main/java/com/owlike/genson/Genson.java
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,8 @@ public <T> T deserialize(GenericType<T> type, Reader reader, Class<? extends Bea
}

public <T> T deserialize(GenericType<T> type, ObjectReader reader, Context ctx) {
recursionCheck(ctx);

Deserializer<T> deser = provideConverter(type.getType());
try {
return deser.deserialize(reader, ctx);
Expand Down Expand Up @@ -420,6 +422,7 @@ public <T> T deserializeInto(Reader reader, T object) {
* @return the object enriched with the properties from the stream.
*/
public <T> T deserializeInto(ObjectReader reader, T object, Context ctx) {
recursionCheck(ctx);
BeanDescriptor<T> bd = (BeanDescriptor<T>) getBeanDescriptorProvider().provide(object.getClass(), this);
bd.deserialize(object, reader, ctx);
return object;
Expand Down Expand Up @@ -475,6 +478,7 @@ public T next() {
if (!hasNext()) throw new NoSuchElementException();
reader.next();
try {
recursionCheck(ctx);
return converter.deserialize(reader, ctx);
} catch (Exception e) {
throw new JsonBindingException("Could not deserialize to type " + type.getRawClass(), e);
Expand Down Expand Up @@ -616,4 +620,25 @@ public RuntimePropertyFilter runtimePropertyFilter() {
public static class Builder extends GensonBuilder {

}

/**
* Updates a counter in the provided context, initializing it to 0 if the counter does not yet exist, throwing a
* runtime exception when a threshold has been reached.
*
* This intends to guard against excessive recursion, causing stack overflow errors.
*
* @param ctx The context on which to maintain a counter
* @throws IllegalStateException When the counter on the context has been increased too often.
*/
public void recursionCheck(Context ctx) {
Integer recursionDepth = ctx.get("recursion-depth", Integer.class);
if (recursionDepth == null) {
recursionDepth = 0;
}
if (recursionDepth >= 1000) { // Arbitrary value to guard against stack-overflow.
throw new IllegalStateException("Max depth limit reached. Unable to recursively deserialize object.");
}
recursionDepth++;
ctx.store("recursion-depth", recursionDepth);
}
}

0 comments on commit e3a22fa

Please sign in to comment.