Skip to content

Commit

Permalink
Skip jar processing on AGP < 7.1.2 if it is a signed multi release ja… (
Browse files Browse the repository at this point in the history
#334)

* Skip jar processing on AGP < 7.1.2 if it is a signed multi release jar, show warning to the user with hint to upgrade AGP

* revert wrong test name

* add changelog entry

* fix formatting issues

* fix build error when used in actual build pipeline. add testcase to SentryPluginMRJarTest

* Update plugin-build/src/main/kotlin/io/sentry/android/gradle/transforms/MetaInfStripTransform.kt

* fix formatting

Co-authored-by: Roman Zavarnitsyn <rom4ek93@gmail.com>
  • Loading branch information
lbloder and romtsn committed Jul 5, 2022
1 parent 9522ed8 commit 6b5bcd9
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 5 deletions.
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#230)
- [diff](https://github.com/getsentry/sentry-cli/compare/1.72.0...2.3.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,13 @@ 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(
"sentry-transformed-${input.nameWithoutExtension}",
".jar"
)
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 +70,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 +108,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" }
}
}

0 comments on commit 6b5bcd9

Please sign in to comment.