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
|
@JvmField
|
||||||
public val LATEST_STABLE_SUPPORTED: JvmMetadataVersion = JvmMetadataVersion(CompilerMetadataVersion.INSTANCE.toArray())
|
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 {
|
override fun write(): Metadata {
|
||||||
throwIfNotWriteable(isAllowedToWrite, "class")
|
throwIfNotWriteable(isAllowedToWrite, "class")
|
||||||
checkMetadataVersion(version)
|
checkMetadataVersionForWrite(version)
|
||||||
return wrapWriteIntoIAE {
|
return wrapWriteIntoIAE {
|
||||||
val writer = ClassWriter(JvmStringTable())
|
val writer = ClassWriter(JvmStringTable())
|
||||||
writer.writeClass(kmClass)
|
writer.writeClass(kmClass)
|
||||||
@@ -198,7 +198,7 @@ public sealed class KotlinClassMetadata {
|
|||||||
|
|
||||||
override fun write(): Metadata {
|
override fun write(): Metadata {
|
||||||
throwIfNotWriteable(isAllowedToWrite, "file facade")
|
throwIfNotWriteable(isAllowedToWrite, "file facade")
|
||||||
checkMetadataVersion(version)
|
checkMetadataVersionForWrite(version)
|
||||||
return wrapWriteIntoIAE {
|
return wrapWriteIntoIAE {
|
||||||
val writer = PackageWriter(JvmStringTable())
|
val writer = PackageWriter(JvmStringTable())
|
||||||
writer.writePackage(kmPackage)
|
writer.writePackage(kmPackage)
|
||||||
@@ -286,7 +286,7 @@ public sealed class KotlinClassMetadata {
|
|||||||
|
|
||||||
override fun write(): Metadata {
|
override fun write(): Metadata {
|
||||||
throwIfNotWriteable(isAllowedToWrite, if (isLambda) "lambda" else "synthetic class")
|
throwIfNotWriteable(isAllowedToWrite, if (isLambda) "lambda" else "synthetic class")
|
||||||
checkMetadataVersion(version)
|
checkMetadataVersionForWrite(version)
|
||||||
return if (isLambda) wrapWriteIntoIAE {
|
return if (isLambda) wrapWriteIntoIAE {
|
||||||
val writer = LambdaWriter(JvmStringTable())
|
val writer = LambdaWriter(JvmStringTable())
|
||||||
writer.writeLambda(kmLambda!!)
|
writer.writeLambda(kmLambda!!)
|
||||||
@@ -424,7 +424,7 @@ public sealed class KotlinClassMetadata {
|
|||||||
|
|
||||||
override fun write(): Metadata {
|
override fun write(): Metadata {
|
||||||
throwIfNotWriteable(isAllowedToWrite, "multi-file class facade")
|
throwIfNotWriteable(isAllowedToWrite, "multi-file class facade")
|
||||||
checkMetadataVersion(version)
|
checkMetadataVersionForWrite(version)
|
||||||
return Metadata(
|
return Metadata(
|
||||||
MULTI_FILE_CLASS_FACADE_KIND, version.toIntArray(),
|
MULTI_FILE_CLASS_FACADE_KIND, version.toIntArray(),
|
||||||
partClassNames.toTypedArray<String>(), extraInt = flags
|
partClassNames.toTypedArray<String>(), extraInt = flags
|
||||||
@@ -506,7 +506,7 @@ public sealed class KotlinClassMetadata {
|
|||||||
|
|
||||||
override fun write(): Metadata {
|
override fun write(): Metadata {
|
||||||
throwIfNotWriteable(isAllowedToWrite, "multi-file class part")
|
throwIfNotWriteable(isAllowedToWrite, "multi-file class part")
|
||||||
checkMetadataVersion(version)
|
checkMetadataVersionForWrite(version)
|
||||||
return wrapWriteIntoIAE {
|
return wrapWriteIntoIAE {
|
||||||
val writer = PackageWriter(JvmStringTable())
|
val writer = PackageWriter(JvmStringTable())
|
||||||
writer.writePackage(kmPackage)
|
writer.writePackage(kmPackage)
|
||||||
@@ -586,7 +586,7 @@ public sealed class KotlinClassMetadata {
|
|||||||
|
|
||||||
override fun write(): Metadata {
|
override fun write(): Metadata {
|
||||||
throwIfNotWriteable(!lenient, "unknown kind")
|
throwIfNotWriteable(!lenient, "unknown kind")
|
||||||
checkMetadataVersion(version)
|
checkMetadataVersionForWrite(version)
|
||||||
return Metadata(
|
return Metadata(
|
||||||
original.kind,
|
original.kind,
|
||||||
version.toIntArray(),
|
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")
|
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)) {
|
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. " +
|
"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]."
|
"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.extraString, after.extraString)
|
||||||
assertEquals(before.packageName, after.packageName)
|
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