mirror of
https://github.com/corda/corda.git
synced 2025-06-19 15:43:52 +00:00
CORDA-702: Don't whitelist certain non-annotated types (#1864)
* Don't whitelist arrays of non-serialisable types for RPC. * Don't whitelist enums which have not been annotated as serialisable.
This commit is contained in:
@ -57,12 +57,13 @@ class CordaClassResolver(serializationContext: SerializationContext) : DefaultCl
|
|||||||
private fun checkClass(type: Class<*>): Registration? {
|
private fun checkClass(type: Class<*>): Registration? {
|
||||||
// If call path has disabled whitelisting (see [CordaKryo.register]), just return without checking.
|
// If call path has disabled whitelisting (see [CordaKryo.register]), just return without checking.
|
||||||
if (!whitelistEnabled) return null
|
if (!whitelistEnabled) return null
|
||||||
// Allow primitives, abstracts and interfaces
|
|
||||||
if (type.isPrimitive || type == Any::class.java || isAbstract(type.modifiers) || type == String::class.java) return null
|
|
||||||
// If array, recurse on element type
|
// If array, recurse on element type
|
||||||
if (type.isArray) return checkClass(type.componentType)
|
if (type.isArray) return checkClass(type.componentType)
|
||||||
// Specialised enum entry, so just resolve the parent Enum type since cannot annotate the specialised entry.
|
// Specialised enum entry, so just resolve the parent Enum type since cannot annotate the specialised entry.
|
||||||
if (!type.isEnum && Enum::class.java.isAssignableFrom(type)) return checkClass(type.superclass)
|
if (!type.isEnum && Enum::class.java.isAssignableFrom(type)) return checkClass(type.superclass)
|
||||||
|
// Allow primitives, abstracts and interfaces. Note that we can also create abstract Enum types,
|
||||||
|
// but we don't want to whitelist those here.
|
||||||
|
if (type.isPrimitive || type == Any::class.java || type == String::class.java || (!type.isEnum && isAbstract(type.modifiers))) return null
|
||||||
// It's safe to have the Class already, since Kryo loads it with initialisation off.
|
// It's safe to have the Class already, since Kryo loads it with initialisation off.
|
||||||
// If we use a whitelist with blacklisting capabilities, whitelist.hasListed(type) may throw an IllegalStateException if input class is blacklisted.
|
// If we use a whitelist with blacklisting capabilities, whitelist.hasListed(type) may throw an IllegalStateException if input class is blacklisted.
|
||||||
// Thus, blacklisting precedes annotation checking.
|
// Thus, blacklisting precedes annotation checking.
|
||||||
|
@ -34,6 +34,23 @@ enum class Foo {
|
|||||||
abstract val value: Int
|
abstract val value: Int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class BadFood {
|
||||||
|
Mud {
|
||||||
|
override val value = -1
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract val value: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
@CordaSerializable
|
||||||
|
enum class Simple {
|
||||||
|
Easy
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class BadSimple {
|
||||||
|
Nasty
|
||||||
|
}
|
||||||
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
open class Element
|
open class Element
|
||||||
|
|
||||||
@ -106,17 +123,36 @@ class CordaClassResolverTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `Annotation on enum works for specialised entries`() {
|
fun `Annotation on enum works for specialised entries`() {
|
||||||
// TODO: Remove this suppress when we upgrade to kotlin 1.1 or when JetBrain fixes the bug.
|
|
||||||
@Suppress("UNSUPPORTED_FEATURE")
|
|
||||||
CordaClassResolver(emptyWhitelistContext).getRegistration(Foo.Bar::class.java)
|
CordaClassResolver(emptyWhitelistContext).getRegistration(Foo.Bar::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = KryoException::class)
|
||||||
|
fun `Unannotated specialised enum does not work`() {
|
||||||
|
CordaClassResolver(emptyWhitelistContext).getRegistration(BadFood.Mud::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Annotation on simple enum works`() {
|
||||||
|
CordaClassResolver(emptyWhitelistContext).getRegistration(Simple.Easy::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = KryoException::class)
|
||||||
|
fun `Unannotated simple enum does not work`() {
|
||||||
|
CordaClassResolver(emptyWhitelistContext).getRegistration(BadSimple.Nasty::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `Annotation on array element works`() {
|
fun `Annotation on array element works`() {
|
||||||
val values = arrayOf(Element())
|
val values = arrayOf(Element())
|
||||||
CordaClassResolver(emptyWhitelistContext).getRegistration(values.javaClass)
|
CordaClassResolver(emptyWhitelistContext).getRegistration(values.javaClass)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = KryoException::class)
|
||||||
|
fun `Unannotated array elements do not work`() {
|
||||||
|
val values = arrayOf(NotSerializable())
|
||||||
|
CordaClassResolver(emptyWhitelistContext).getRegistration(values.javaClass)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `Annotation not needed on abstract class`() {
|
fun `Annotation not needed on abstract class`() {
|
||||||
CordaClassResolver(emptyWhitelistContext).getRegistration(AbstractClass::class.java)
|
CordaClassResolver(emptyWhitelistContext).getRegistration(AbstractClass::class.java)
|
||||||
|
Reference in New Issue
Block a user