CORDA-653 - Serialised enums should respect whitelist (#1692)

This commit is contained in:
Katelyn Baker 2017-09-27 18:02:35 +01:00 committed by Rick Parker
parent c8fc1b624b
commit 5ed755d3fe
3 changed files with 83 additions and 0 deletions

View File

@ -9,6 +9,10 @@ UNRELEASED
* ``Cordapp`` now has a name field for identifying CorDapps and all CorDapp names are printed to console at startup.
* Enums now respsect the whitelist applied to the Serializer factory serializing / deserializing them. If the enum isn't
either annotated with the @CordaSerializable annotation or explicitly whitelisted then a NotSerializableException is
thrown.
Release 1.0
-----------

View File

@ -82,6 +82,7 @@ class SerializerFactory(val whitelist: ClassWhitelist, cl: ClassLoader) {
}
}
Enum::class.java.isAssignableFrom(actualClass ?: declaredClass) -> serializersByType.computeIfAbsent(actualClass ?: declaredClass) {
whitelisted(actualType)
EnumSerializer(actualType, actualClass ?: declaredClass, this)
}
else -> makeClassSerializer(actualClass ?: declaredClass, actualType, declaredType)

View File

@ -1,5 +1,7 @@
package net.corda.nodeapi.internal.serialization.amqp
import net.corda.core.serialization.ClassWhitelist
import net.corda.core.serialization.CordaSerializable
import org.junit.Test
import java.time.DayOfWeek
@ -10,12 +12,18 @@ import java.io.File
import java.io.NotSerializableException
import net.corda.core.serialization.SerializedBytes
import org.assertj.core.api.Assertions
class EnumTests {
enum class Bras {
TSHIRT, UNDERWIRE, PUSHUP, BRALETTE, STRAPLESS, SPORTS, BACKLESS, PADDED
}
@CordaSerializable
enum class AnnotatedBras {
TSHIRT, UNDERWIRE, PUSHUP, BRALETTE, STRAPLESS, SPORTS, BACKLESS, PADDED
}
// The state of the OldBras enum when the tests in changedEnum1 were serialised
// - use if the test file needs regenerating
//enum class OldBras {
@ -186,4 +194,74 @@ class EnumTests {
// we expect this to throw
DeserializationInput(sf1).deserialize(SerializedBytes<C>(sc2))
}
@Test
fun enumNotWhitelistedFails() {
data class C (val c: Bras)
class WL (val allowed: String): ClassWhitelist {
override fun hasListed(type: Class<*>): Boolean {
return type.name == allowed
}
}
val factory = SerializerFactory(WL(classTestName("C")), ClassLoader.getSystemClassLoader())
Assertions.assertThatThrownBy {
TestSerializationOutput(VERBOSE, factory).serialize(C(Bras.UNDERWIRE))
}.isInstanceOf(NotSerializableException::class.java)
}
@Test
fun enumWhitelisted() {
data class C (val c: Bras)
class WL : ClassWhitelist {
override fun hasListed(type: Class<*>): Boolean {
return type.name == "net.corda.nodeapi.internal.serialization.amqp.EnumTests\$enumWhitelisted\$C" ||
type.name == "net.corda.nodeapi.internal.serialization.amqp.EnumTests\$Bras"
}
}
val factory = SerializerFactory(WL(), ClassLoader.getSystemClassLoader())
// if it all works, this won't explode
TestSerializationOutput(VERBOSE, factory).serialize(C(Bras.UNDERWIRE))
}
@Test
fun enumAnnotated() {
@CordaSerializable data class C (val c: AnnotatedBras)
class WL : ClassWhitelist {
override fun hasListed(type: Class<*>) = false
}
val factory = SerializerFactory(WL(), ClassLoader.getSystemClassLoader())
// if it all works, this won't explode
TestSerializationOutput(VERBOSE, factory).serialize(C(AnnotatedBras.UNDERWIRE))
}
@Test
fun deserializeNonWhitlistedEnum() {
data class C (val c: Bras)
class WL (val allowed: List<String>) : ClassWhitelist {
override fun hasListed(type: Class<*>) = type.name in allowed
}
// first serialise the class using a context in which Bras are whitelisted
val factory = SerializerFactory(WL(listOf (classTestName("C"),
"net.corda.nodeapi.internal.serialization.amqp.EnumTests\$Bras")),
ClassLoader.getSystemClassLoader())
val bytes = TestSerializationOutput(VERBOSE, factory).serialize(C(Bras.UNDERWIRE))
// then take that serialised object and attempt to deserialize it in a context that
// disallows the Bras enum
val factory2 = SerializerFactory(WL(listOf (classTestName("C"))), ClassLoader.getSystemClassLoader())
Assertions.assertThatThrownBy {
DeserializationInput(factory2).deserialize(bytes)
}.isInstanceOf(NotSerializableException::class.java)
}
}