diff --git a/genson/src/main/java/com/owlike/genson/Genson.java b/genson/src/main/java/com/owlike/genson/Genson.java index cf42fd09..b2c3e9cf 100644 --- a/genson/src/main/java/com/owlike/genson/Genson.java +++ b/genson/src/main/java/com/owlike/genson/Genson.java @@ -377,6 +377,8 @@ public T deserialize(GenericType type, Reader reader, Class T deserialize(GenericType type, ObjectReader reader, Context ctx) { + recursionCheck(ctx); + Deserializer deser = provideConverter(type.getType()); try { return deser.deserialize(reader, ctx); @@ -420,6 +422,7 @@ public T deserializeInto(Reader reader, T object) { * @return the object enriched with the properties from the stream. */ public T deserializeInto(ObjectReader reader, T object, Context ctx) { + recursionCheck(ctx); BeanDescriptor bd = (BeanDescriptor) getBeanDescriptorProvider().provide(object.getClass(), this); bd.deserialize(object, reader, ctx); return object; @@ -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); @@ -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); + } }