Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skip jar processing on AGP < 7.1.2 if it is a signed multi release jaโ€ฆ #334

Merged
merged 11 commits into from Jul 5, 2022
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -8,6 +8,10 @@
- [changelog](https://github.com/getsentry/sentry-cli/blob/master/CHANGELOG.md#220)
- [diff](https://github.com/getsentry/sentry-cli/compare/1.72.0...2.2.0)

### Fixes

- Skip jar processing on AGP < 7.1.2 for signed multi release jars ([#334](https://github.com/getsentry/sentry-android-gradle-plugin/pull/334))

## 3.1.2

### Features
Expand Down
@@ -1,6 +1,9 @@
package io.sentry.android.gradle.transforms

import io.sentry.android.gradle.SentryPlugin
import io.sentry.android.gradle.util.warn
import java.io.File
import java.nio.file.Files
import java.util.jar.Attributes
import java.util.jar.JarEntry
import java.util.jar.JarFile
Expand Down Expand Up @@ -50,9 +53,10 @@ abstract class MetaInfStripTransform : TransformAction<MetaInfStripTransform.Par
val input = inputArtifact.get().asFile
val jarFile = JarFile(input)
if (jarFile.isMultiRelease) {
val output = outputs.file("${input.nameWithoutExtension}-meta-inf-stripped.jar")
val outputFilename = "${input.nameWithoutExtension}-meta-inf-stripped.jar"
val tmpOutputFile = File.createTempFile("tmp-${input.nameWithoutExtension}", ".jar")
romtsn marked this conversation as resolved.
Show resolved Hide resolved
var isStillMultiRelease = false
output.jarOutputStream().use { outStream ->
tmpOutputFile.jarOutputStream().use { outStream ->
val entries = jarFile.entries()
// copy each .jar entry, except those that are under META-INF/versions/${unsupported_java_version}
while (entries.hasMoreElements()) {
Expand All @@ -63,6 +67,19 @@ abstract class MetaInfStripTransform : TransformAction<MetaInfStripTransform.Par
continue
}

if (jarEntry.isSignatureEntry) {
SentryPlugin.logger.warn {
"""
Signed Multirelease Jar (${jarFile.name}) found, skipping transform.
This might lead to auto-instrumentation issues due to a bug in AGP (https://issuetracker.google.com/issues/206655905).
Please update to AGP >= 7.1.2 (https://developer.android.com/studio/releases/gradle-plugin) in order to keep using `autoInstrumentation` option.
""".trimIndent()
}
tmpOutputFile.delete()
outputs.file(inputArtifact)
return
}

if (jarEntry.name.startsWith(versionsDir, ignoreCase = true)) {
val javaVersion = jarEntry.javaVersion
if (javaVersion > MIN_SUPPORTED_JAVA_VERSION) {
Expand All @@ -88,17 +105,23 @@ abstract class MetaInfStripTransform : TransformAction<MetaInfStripTransform.Par
outStream.closeEntry()
}
}
val transformedOutput = outputs.file(outputFilename)
Files.move(tmpOutputFile.toPath(), transformedOutput.toPath())
} else {
outputs.file(inputArtifact)
}
}

private val JarEntry.isSignatureEntry get() = signatureFileRegex.matches(name)

private val JarEntry.javaVersion: Int get() = regex.find(name)?.value?.toIntOrNull() ?: 0

private fun File.jarOutputStream(): JarOutputStream = JarOutputStream(outputStream())

companion object {
private val regex = "(?<=/)([0-9]*)(?=/)".toRegex()
private val signatureFileRegex = "^META-INF/.*\\.(SF|DSA|RSA|EC)|^META-INF/SIG-.*"
.toRegex()
private const val versionsDir = "META-INF/versions/"
private const val MIN_SUPPORTED_JAVA_VERSION = 11

Expand Down
Expand Up @@ -33,5 +33,33 @@ class SentryPluginMRJarTest :
assertTrue { "BUILD SUCCESSFUL" in result.output }
}

@Test
fun `shows a warning when there is a signed MR-JAR dependency`() {
appBuildFile.writeText(
// language=Groovy
"""
plugins {
id "com.android.application"
id "io.sentry.android.gradle"
}

dependencies {
implementation("org.bouncycastle:bcprov-jdk15on:1.63")
}

sentry.tracingInstrumentation.enabled = true
""".trimIndent()
)

val result = runner
.appendArguments("app:assembleDebug")
.build()

print(result.output)

assertTrue { "Please update to AGP >= 7.1.2" in result.output }
assertTrue { "BUILD SUCCESSFUL" in result.output }
}

override val additionalRootProjectConfig: String = ""
}
Expand Up @@ -31,20 +31,26 @@ class MetaInfStripTransformTest {
tmpDir: TemporaryFolder,
jarName: String = "test.jar",
multiRelease: Boolean = true,
includeSupportedVersion: Boolean = false
includeSupportedVersion: Boolean = false,
signed: Boolean = false
): MetaInfStripTransform {
val file = tmpDir.newFile(jarName)
val jar = file.toJar(
multiRelease = multiRelease,
includeSupportedVersion = includeSupportedVersion
includeSupportedVersion = includeSupportedVersion,
signed = signed
)

whenever(provider.get()).thenReturn(RegularFile { jar })

return TestMetaInfStripTransform(provider)
}

private fun File.toJar(multiRelease: Boolean, includeSupportedVersion: Boolean): File {
private fun File.toJar(
multiRelease: Boolean,
includeSupportedVersion: Boolean,
signed: Boolean
): File {
JarOutputStream(outputStream()).use {
// normal classpath
it.putNextEntry(ZipEntry("com/squareup/moshi/Types.class"))
Expand Down Expand Up @@ -100,6 +106,11 @@ class MetaInfStripTransformTest {
)
it.closeEntry()
}

if (signed) {
it.putNextEntry(ZipEntry("META-INF/SIGNING_FILE.SF"))
it.putNextEntry(ZipEntry("META-INF/SIGNING_FILE.DSA"))
}
}

// manifest
Expand Down Expand Up @@ -154,6 +165,7 @@ class MetaInfStripTransformTest {
val outputs = FakeTransformOutputs(tmp)

val sut = fixture.getSut(tmp)

sut.transform(outputs)

val jar = JarFile(outputs.outputFile)
Expand Down Expand Up @@ -218,4 +230,17 @@ class MetaInfStripTransformTest {
}
return entries
}

@Test
fun `when multi-release signed-jar, skip transform`() {
val outputs = FakeTransformOutputs(tmp)

val sut = fixture.getSut(tmp, includeSupportedVersion = true, signed = true)
sut.transform(outputs)

val jar = JarFile(outputs.outputFile)

assertTrue { jar.read().any { it.key.startsWith("META-INF/versions/16") } }
assertTrue { outputs.outputFile.name == "test.jar" }
}
}