From 32a4a6fcc776e3af95e36dc811b99c625393a888 Mon Sep 17 00:00:00 2001 From: Richard Marmorstein Date: Tue, 20 Dec 2022 13:06:09 -0600 Subject: [PATCH 1/2] Replace ReflectionCheckingTypeAdapterFactory with a Filter --- build.gradle | 2 +- src/main/java/com/stripe/net/ApiResource.java | 13 +++++++++- ...ApiResourceTypeAdapterFactoryProvider.java | 1 - .../ReflectionCheckingTypeAdapterFactory.java | 26 ------------------- 4 files changed, 13 insertions(+), 29 deletions(-) delete mode 100644 src/main/java/com/stripe/net/ReflectionCheckingTypeAdapterFactory.java diff --git a/build.gradle b/build.gradle index f466cab8401..159aa29a373 100644 --- a/build.gradle +++ b/build.gradle @@ -82,7 +82,7 @@ repositories { dependencies { errorprone group: "com.google.errorprone", name: "error_prone_core", version: "2.10.0" errorproneJavac group: "com.google.errorprone", name: "javac", version:"9+181-r4173-1" - implementation group: "com.google.code.gson", name: "gson", version:"2.9.0" + implementation group: "com.google.code.gson", name: "gson", version:"2.9.1" testImplementation group: "com.google.guava", name: "guava", version:"31.0.1-jre" testImplementation group: "com.squareup.okhttp3", name: "mockwebserver", version: "4.9.1" testImplementation group: "org.mockito", name: "mockito-core", version:"4.1.0" diff --git a/src/main/java/com/stripe/net/ApiResource.java b/src/main/java/com/stripe/net/ApiResource.java index aeb9257aae6..02bcbb292ed 100644 --- a/src/main/java/com/stripe/net/ApiResource.java +++ b/src/main/java/com/stripe/net/ApiResource.java @@ -3,6 +3,7 @@ import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.google.gson.ReflectionAccessFilter; import com.google.gson.TypeAdapterFactory; import com.stripe.Stripe; import com.stripe.exception.InvalidRequestException; @@ -36,7 +37,17 @@ private static Gson createGson() { .registerTypeAdapter(Event.Data.class, new EventDataDeserializer()) .registerTypeAdapter(Event.Request.class, new EventRequestDeserializer()) .registerTypeAdapter(ExpandableField.class, new ExpandableFieldDeserializer()) - .registerTypeAdapter(StripeRawJsonObject.class, new StripeRawJsonObjectDeserializer()); + .registerTypeAdapter(StripeRawJsonObject.class, new StripeRawJsonObjectDeserializer()) + .addReflectionAccessFilter( + new ReflectionAccessFilter() { + @Override + public ReflectionAccessFilter.FilterResult check(Class rawClass) { + if (rawClass.getTypeName().startsWith("com.stripe.")) { + return ReflectionAccessFilter.FilterResult.ALLOW; + } + return ReflectionAccessFilter.FilterResult.BLOCK_ALL; + } + }); for (TypeAdapterFactory factory : ApiResourceTypeAdapterFactoryProvider.getAll()) { builder.registerTypeAdapterFactory(factory); diff --git a/src/main/java/com/stripe/net/ApiResourceTypeAdapterFactoryProvider.java b/src/main/java/com/stripe/net/ApiResourceTypeAdapterFactoryProvider.java index 16076c6e931..dd8cada57e5 100644 --- a/src/main/java/com/stripe/net/ApiResourceTypeAdapterFactoryProvider.java +++ b/src/main/java/com/stripe/net/ApiResourceTypeAdapterFactoryProvider.java @@ -18,7 +18,6 @@ final class ApiResourceTypeAdapterFactoryProvider { factories.add(new BalanceTransactionSourceTypeAdapterFactory()); factories.add(new ExternalAccountTypeAdapterFactory()); factories.add(new PaymentSourceTypeAdapterFactory()); - factories.add(new ReflectionCheckingTypeAdapterFactory()); } public static List getAll() { diff --git a/src/main/java/com/stripe/net/ReflectionCheckingTypeAdapterFactory.java b/src/main/java/com/stripe/net/ReflectionCheckingTypeAdapterFactory.java deleted file mode 100644 index 40acde38b58..00000000000 --- a/src/main/java/com/stripe/net/ReflectionCheckingTypeAdapterFactory.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.stripe.net; - -import com.google.gson.Gson; -import com.google.gson.TypeAdapter; -import com.google.gson.TypeAdapterFactory; -import com.google.gson.internal.bind.ReflectiveTypeAdapterFactory; -import com.google.gson.reflect.TypeToken; - -/** - * {@link TypeAdapterFactory} that checks that we don't use {@link ReflectiveTypeAdapterFactory} - * accidentally for classes outside {@code com.stripe} packages. This usually happens when we forget - * to mark a field {@code transient}. - */ -class ReflectionCheckingTypeAdapterFactory implements TypeAdapterFactory { - @Override - public TypeAdapter create(Gson gson, TypeToken type) { - if (!type.getType().getTypeName().startsWith("com.stripe.")) { - TypeAdapter adapter = gson.getDelegateAdapter(this, type); - if (adapter instanceof ReflectiveTypeAdapterFactory.Adapter) { - throw new IllegalArgumentException( - "Refusing to create type reflection-based type adapter for external class: " + type); - } - } - return null; - } -} From e0f69fabfb0c5160dd5142c56bc7f96f9333712e Mon Sep 17 00:00:00 2001 From: Richard Marmorstein Date: Tue, 20 Dec 2022 14:14:18 -0600 Subject: [PATCH 2/2] Add test --- .../java/com/stripe/net/ApiResourceTest.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/test/java/com/stripe/net/ApiResourceTest.java b/src/test/java/com/stripe/net/ApiResourceTest.java index b526168142f..5f70efb8953 100644 --- a/src/test/java/com/stripe/net/ApiResourceTest.java +++ b/src/test/java/com/stripe/net/ApiResourceTest.java @@ -2,8 +2,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import com.google.gson.JsonIOException; import com.stripe.exception.InvalidRequestException; +import java.net.Proxy; import org.junit.jupiter.api.Test; class ApiResourceTest { @@ -23,4 +26,17 @@ public void testUrlEncodeIdThrowingOnNull() { ApiResource.urlEncodeId(null); }); } + + static class MyClass extends ApiResource { + public Proxy proxy; + } + + @Test + public void testReflectionFilter() { + JsonIOException e = + assertThrows(JsonIOException.class, () -> ApiResource.GSON.fromJson("{}", MyClass.class)); + + // Assert that the error message involves a ReflectionAccessFilter. + assertTrue(e.getMessage().contains("ReflectionAccessFilter")); + } }