From 656dc549b16900f93dbbdce77c6b07cb4fccaa7e Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Mon, 11 Jul 2022 17:45:24 +0200 Subject: [PATCH] Reject JDK proxy hint registration for sealed interfaces Closes gh-28786 --- .../aot/hint/JdkProxyHint.java | 10 ++++---- .../aot/hint/ProxyHintsTests.java | 23 +++++++++++++++---- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/aot/hint/JdkProxyHint.java b/spring-core/src/main/java/org/springframework/aot/hint/JdkProxyHint.java index c8c7af2ccd..bdf58a06c8 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/JdkProxyHint.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/JdkProxyHint.java @@ -151,10 +151,12 @@ public final class JdkProxyHint implements ConditionalHint { } private static List toTypeReferences(Class... proxiedInterfaces) { - List concreteTypes = Arrays.stream(proxiedInterfaces) - .filter(candidate -> !candidate.isInterface()).map(Class::getName).toList(); - if (!concreteTypes.isEmpty()) { - throw new IllegalArgumentException("Not an interface: " + concreteTypes); + List invalidTypes = Arrays.stream(proxiedInterfaces) + .filter(candidate -> !candidate.isInterface() || candidate.isSealed()) + .map(Class::getName) + .toList(); + if (!invalidTypes.isEmpty()) { + throw new IllegalArgumentException("The following must be non-sealed interfaces: " + invalidTypes); } return Arrays.stream(proxiedInterfaces).map(TypeReference::of).toList(); } diff --git a/spring-core/src/test/java/org/springframework/aot/hint/ProxyHintsTests.java b/spring-core/src/test/java/org/springframework/aot/hint/ProxyHintsTests.java index ffafa942e0..f204bedd46 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/ProxyHintsTests.java +++ b/spring-core/src/test/java/org/springframework/aot/hint/ProxyHintsTests.java @@ -39,17 +39,25 @@ class ProxyHintsTests { @Test - void registerJdkProxyWithInterfaceClass() { - this.proxyHints.registerJdkProxy(Function.class); - assertThat(this.proxyHints.jdkProxies()).singleElement().satisfies(proxiedInterfaces(Function.class)); + void registerJdkProxyWithSealedInterface() { + assertThatIllegalArgumentException() + .isThrownBy(() -> this.proxyHints.registerJdkProxy(SealedInterface.class)) + .withMessageContaining(SealedInterface.class.getName()); } @Test void registerJdkProxyWithConcreteClass() { - assertThatIllegalArgumentException().isThrownBy(() -> this.proxyHints.registerJdkProxy(String.class)) + assertThatIllegalArgumentException() + .isThrownBy(() -> this.proxyHints.registerJdkProxy(String.class)) .withMessageContaining(String.class.getName()); } + @Test + void registerJdkProxyWithInterface() { + this.proxyHints.registerJdkProxy(Function.class); + assertThat(this.proxyHints.jdkProxies()).singleElement().satisfies(proxiedInterfaces(Function.class)); + } + @Test void registerJdkProxyWithTypeReferences() { this.proxyHints.registerJdkProxy(TypeReference.of(Function.class), TypeReference.of("com.example.Advised")); @@ -128,4 +136,11 @@ class ProxyHintsTests { return Arrays.stream(proxiedInterfaces).map(TypeReference::of).toArray(TypeReference[]::new); } + + sealed interface SealedInterface { + } + + static final class SealedClass implements SealedInterface { + } + }