Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixes #191 and #192: Guard against stack overflow #194

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions genson/src/main/java/com/owlike/genson/Genson.java
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ public void serialize(Object object, ObjectWriter writer, Context ctx) {
* writer instance you also must ensure to call close on it when you are done.
*/
public void serialize(Object object, Type type, ObjectWriter writer, Context ctx) {
recursionCheck(ctx);
Serializer<Object> ser = provideConverter(type);
try {
ser.serialize(object, writer, ctx);
Expand Down Expand Up @@ -377,6 +378,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 +423,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 +479,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 +621,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);
}
}