Do not allow writing metadata versions that are too high
because a format may be incorrect for future compilers #KT-64230 Fixed
This commit is contained in:
committed by
Space Team
parent
0d4dfbcf0c
commit
af23706a9a
@@ -112,5 +112,8 @@ public class JvmMetadataVersion(public val major: Int, public val minor: Int, pu
|
||||
*/
|
||||
@JvmField
|
||||
public val LATEST_STABLE_SUPPORTED: JvmMetadataVersion = JvmMetadataVersion(CompilerMetadataVersion.INSTANCE.toArray())
|
||||
|
||||
@JvmField
|
||||
internal val HIGHEST_ALLOWED_TO_WRITE: JvmMetadataVersion = JvmMetadataVersion(CompilerMetadataVersion.INSTANCE_NEXT.toArray())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ public sealed class KotlinClassMetadata {
|
||||
|
||||
override fun write(): Metadata {
|
||||
throwIfNotWriteable(isAllowedToWrite, "class")
|
||||
checkMetadataVersion(version)
|
||||
checkMetadataVersionForWrite(version)
|
||||
return wrapWriteIntoIAE {
|
||||
val writer = ClassWriter(JvmStringTable())
|
||||
writer.writeClass(kmClass)
|
||||
@@ -198,7 +198,7 @@ public sealed class KotlinClassMetadata {
|
||||
|
||||
override fun write(): Metadata {
|
||||
throwIfNotWriteable(isAllowedToWrite, "file facade")
|
||||
checkMetadataVersion(version)
|
||||
checkMetadataVersionForWrite(version)
|
||||
return wrapWriteIntoIAE {
|
||||
val writer = PackageWriter(JvmStringTable())
|
||||
writer.writePackage(kmPackage)
|
||||
@@ -286,7 +286,7 @@ public sealed class KotlinClassMetadata {
|
||||
|
||||
override fun write(): Metadata {
|
||||
throwIfNotWriteable(isAllowedToWrite, if (isLambda) "lambda" else "synthetic class")
|
||||
checkMetadataVersion(version)
|
||||
checkMetadataVersionForWrite(version)
|
||||
return if (isLambda) wrapWriteIntoIAE {
|
||||
val writer = LambdaWriter(JvmStringTable())
|
||||
writer.writeLambda(kmLambda!!)
|
||||
@@ -424,7 +424,7 @@ public sealed class KotlinClassMetadata {
|
||||
|
||||
override fun write(): Metadata {
|
||||
throwIfNotWriteable(isAllowedToWrite, "multi-file class facade")
|
||||
checkMetadataVersion(version)
|
||||
checkMetadataVersionForWrite(version)
|
||||
return Metadata(
|
||||
MULTI_FILE_CLASS_FACADE_KIND, version.toIntArray(),
|
||||
partClassNames.toTypedArray<String>(), extraInt = flags
|
||||
@@ -506,7 +506,7 @@ public sealed class KotlinClassMetadata {
|
||||
|
||||
override fun write(): Metadata {
|
||||
throwIfNotWriteable(isAllowedToWrite, "multi-file class part")
|
||||
checkMetadataVersion(version)
|
||||
checkMetadataVersionForWrite(version)
|
||||
return wrapWriteIntoIAE {
|
||||
val writer = PackageWriter(JvmStringTable())
|
||||
writer.writePackage(kmPackage)
|
||||
@@ -586,7 +586,7 @@ public sealed class KotlinClassMetadata {
|
||||
|
||||
override fun write(): Metadata {
|
||||
throwIfNotWriteable(!lenient, "unknown kind")
|
||||
checkMetadataVersion(version)
|
||||
checkMetadataVersionForWrite(version)
|
||||
return Metadata(
|
||||
original.kind,
|
||||
version.toIntArray(),
|
||||
@@ -817,11 +817,14 @@ public sealed class KotlinClassMetadata {
|
||||
throw IllegalArgumentException("This $name cannot be written because it represents metadata read in lenient mode")
|
||||
}
|
||||
|
||||
internal fun checkMetadataVersion(version: JvmMetadataVersion) {
|
||||
private fun checkMetadataVersionForWrite(version: JvmMetadataVersion) {
|
||||
require(version.major >= 1 && (version.major > 1 || version.minor >= 4)) {
|
||||
"This version of kotlinx-metadata-jvm doesn't support writing Kotlin metadata of version earlier than 1.4. " +
|
||||
"Please change the version from $version to at least [1, 4]."
|
||||
}
|
||||
require(version <= JvmMetadataVersion.HIGHEST_ALLOWED_TO_WRITE) {
|
||||
"kotlinx-metadata-jvm cannot write metadata for future compiler versions. Requested to write version $version, but highest known version is ${JvmMetadataVersion.HIGHEST_ALLOWED_TO_WRITE}"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -48,4 +48,22 @@ class WritersContractTest {
|
||||
assertEquals(before.extraString, after.extraString)
|
||||
assertEquals(before.packageName, after.packageName)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun futureVersionCantBeWritten() = everyType.forEach { before ->
|
||||
val md = KotlinClassMetadata.readStrict(before)
|
||||
md.version = JvmMetadataVersion(3, 4, 5)
|
||||
assertFailsWith<IllegalArgumentException> { md.write() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun nextVersionWrite() = everyType.forEach { before ->
|
||||
val md = KotlinClassMetadata.readStrict(before)
|
||||
val ver = md.version
|
||||
assertEquals(2, ver.major) // to correctly handle future case 2.x -> 3.0
|
||||
md.version = JvmMetadataVersion(ver.major, ver.minor + 1, ver.patch)
|
||||
md.write() // OK
|
||||
md.version = JvmMetadataVersion(ver.major, ver.minor + 2, ver.patch)
|
||||
assertFailsWith<IllegalArgumentException> { md.write() }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user