From c5311bd7e945597e4056875ef35265fac0e43dba Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Tue, 25 Jul 2023 21:17:07 +0200 Subject: [PATCH] Validate instances created by InstanceCreator --- .../gson/internal/ConstructorConstructor.java | 17 ++++++- .../gson/functional/InstanceCreatorTest.java | 47 ++++++++++++++++++- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/gson/src/main/java/com/google/gson/internal/ConstructorConstructor.java b/gson/src/main/java/com/google/gson/internal/ConstructorConstructor.java index 0f488a9bb9..9f9f73f7e3 100644 --- a/gson/src/main/java/com/google/gson/internal/ConstructorConstructor.java +++ b/gson/src/main/java/com/google/gson/internal/ConstructorConstructor.java @@ -89,6 +89,19 @@ static String checkInstantiable(Class c) { return null; } + private static T useInstanceCreator(InstanceCreator instanceCreator, Type type, Class rawType) { + T instance = instanceCreator.createInstance(type); + if (instance == null) { + throw new RuntimeException("InstanceCreator " + instanceCreator + " returned null for type " + type); + } + + if (!rawType.isInstance(instance)) { + throw new ClassCastException("InstanceCreator " + instanceCreator + " created instance of wrong type;" + + " expected " + rawType.getName() + " but got instance of unrelated type " + instance.getClass().getName()); + } + return instance; + } + public ObjectConstructor get(TypeToken typeToken) { final Type type = typeToken.getType(); final Class rawType = typeToken.getRawType(); @@ -100,7 +113,7 @@ public ObjectConstructor get(TypeToken typeToken) { if (typeCreator != null) { return new ObjectConstructor() { @Override public T construct() { - return typeCreator.createInstance(type); + return useInstanceCreator(typeCreator, type, rawType); } }; } @@ -112,7 +125,7 @@ public ObjectConstructor get(TypeToken typeToken) { if (rawTypeCreator != null) { return new ObjectConstructor() { @Override public T construct() { - return rawTypeCreator.createInstance(type); + return useInstanceCreator(rawTypeCreator, type, rawType); } }; } diff --git a/gson/src/test/java/com/google/gson/functional/InstanceCreatorTest.java b/gson/src/test/java/com/google/gson/functional/InstanceCreatorTest.java index ea3f979983..842dd4cf83 100644 --- a/gson/src/test/java/com/google/gson/functional/InstanceCreatorTest.java +++ b/gson/src/test/java/com/google/gson/functional/InstanceCreatorTest.java @@ -17,6 +17,7 @@ package com.google.gson.functional; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -33,7 +34,7 @@ import org.junit.Test; /** - * Functional Test exercising custom serialization only. When test applies to both + * Functional Test exercising custom deserialization only. When test applies to both * serialization and deserialization then add it to CustomTypeAdapterTest. * * @author Inderjeet Singh @@ -129,4 +130,48 @@ class SubTreeSet extends TreeSet {} assertThat(set.first()).isEqualTo("b"); assertThat(set.getClass()).isEqualTo(SubTreeSet.class); } + + private static class CustomClass {} + + @Test + public void testInstanceCreatorReturnsNull() { + Gson gson = new GsonBuilder() + .registerTypeAdapter(CustomClass.class, new InstanceCreator() { + @Override + public CustomClass createInstance(Type type) { + return null; + } + + @Override + public String toString() { + return "bad-instance-creator"; + } + }) + .create(); + + RuntimeException e = assertThrows(RuntimeException.class, () -> gson.fromJson("{}", CustomClass.class)); + assertThat(e).hasMessageThat().isEqualTo("InstanceCreator bad-instance-creator returned null for" + + " type class " + CustomClass.class.getName()); + } + + @Test + public void testInstanceCreatorReturnsWrongInstance() { + Gson gson = new GsonBuilder() + .registerTypeAdapter(CustomClass.class, new InstanceCreator() { + @Override + public String createInstance(Type type) { + return "test"; + } + + @Override + public String toString() { + return "bad-instance-creator"; + } + }) + .create(); + + ClassCastException e = assertThrows(ClassCastException.class, () -> gson.fromJson("{}", CustomClass.class)); + assertThat(e).hasMessageThat().isEqualTo("InstanceCreator bad-instance-creator created instance of wrong type;" + + " expected " + CustomClass.class.getName() + " but got instance of unrelated type java.lang.String"); + } }