FastJarFS: fix behavior on invalid zip files

"emulate" the ZipHandler - log error and ignore invalid file
#KT-55712 fixed
This commit is contained in:
Ilya Chernikov
2023-01-31 11:26:08 +01:00
committed by Space Team
parent b415aa7446
commit 46c8cbe1bb
2 changed files with 66 additions and 1 deletions
@@ -4,12 +4,14 @@
*/ */
package org.jetbrains.kotlin.cli.jvm.compiler.jarfs package org.jetbrains.kotlin.cli.jvm.compiler.jarfs
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.util.text.StringUtil
import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFile
import java.io.File import java.io.File
import java.io.FileNotFoundException import java.io.FileNotFoundException
import java.io.RandomAccessFile import java.io.RandomAccessFile
import java.nio.channels.FileChannel import java.nio.channels.FileChannel
import kotlin.collections.HashMap
class FastJarHandler(val fileSystem: FastJarFileSystem, path: String) { class FastJarHandler(val fileSystem: FastJarFileSystem, path: String) {
private val myRoot: VirtualFile? private val myRoot: VirtualFile?
@@ -25,7 +27,10 @@ class FastJarHandler(val fileSystem: FastJarFileSystem, path: String) {
entries = try { entries = try {
mappedByteBuffer.parseCentralDirectory() mappedByteBuffer.parseCentralDirectory()
} catch (e: Exception) { } catch (e: Exception) {
throw IllegalStateException("Error while reading '${file.path}': $e", e) // copying the behavior of ArchiveHandler (and therefore ZipHandler)
// TODO: consider propagating to compiler error or warning, but take into account that both javac and K1 simply ignore invalid jars in such cases
Logger.getInstance(this::class.java).warn("Error while reading zip file: ${file.path}: $e", e)
emptyList()
} }
cachedManifest = cachedManifest =
entries.singleOrNull { StringUtil.equals(MANIFEST_PATH, it.relativePath) } entries.singleOrNull { StringUtil.equals(MANIFEST_PATH, it.relativePath) }
@@ -5,12 +5,16 @@
package org.jetbrains.kotlin.jvm.compiler package org.jetbrains.kotlin.jvm.compiler
import com.intellij.core.JavaCoreApplicationEnvironment
import com.intellij.openapi.util.Disposer
import junit.framework.TestCase import junit.framework.TestCase
import org.jetbrains.kotlin.cli.jvm.compiler.jarfs.FastJarFileSystem import org.jetbrains.kotlin.cli.jvm.compiler.jarfs.FastJarFileSystem
import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.KotlinTestUtils
import org.junit.Assert import org.junit.Assert
import java.io.ByteArrayOutputStream
import java.io.File import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
import java.io.PrintStream
import java.util.zip.ZipEntry import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream import java.util.zip.ZipOutputStream
@@ -18,13 +22,18 @@ import java.util.zip.ZipOutputStream
class FastJarFSTest : TestCase() { class FastJarFSTest : TestCase() {
private var fs: FastJarFileSystem? = null private var fs: FastJarFileSystem? = null
private var coreAppEnv: JavaCoreApplicationEnvironment? = null
private val rootDisposable = Disposer.newDisposable()
override fun setUp() { override fun setUp() {
super.setUp() super.setUp()
fs = FastJarFileSystem.createIfUnmappingPossible() fs = FastJarFileSystem.createIfUnmappingPossible()
coreAppEnv = JavaCoreApplicationEnvironment(rootDisposable)
} }
override fun tearDown() { override fun tearDown() {
coreAppEnv = null
rootDisposable.dispose()
fs?.clearHandlersCache() fs?.clearHandlersCache()
fs = null fs = null
super.tearDown() super.tearDown()
@@ -57,4 +66,55 @@ class FastJarFSTest : TestCase() {
Assert.assertEquals(String(file.contentsToByteArray()), i.toString()) Assert.assertEquals(String(file.contentsToByteArray()), i.toString())
} }
} }
fun testInvalidJar() {
val fs = fs ?: return
val tmpDir = KotlinTestUtils.tmpDirForTest(this)
val badJarFile = File(tmpDir, "file.pom")
badJarFile.writeText(A_POM_FILE)
val errFromFastJarFs = captureErr {
fs.findFileByPath(badJarFile.absolutePath + "!/a.class")
}
Assert.assertTrue(errFromFastJarFs.contains("WARN: Error while reading zip file:"))
val errFromCoreJarFs = captureErr {
coreAppEnv!!.jarFileSystem.findFileByPath(badJarFile.absolutePath + "!/a.class")
}
// Asserting that core jar FS still behaves the same way as the "emulation" implemented in FastJarFS
Assert.assertTrue(errFromCoreJarFs.contains("WARN: error in opening zip file"))
}
} }
private fun captureErr(body: () -> Unit): String {
val outStream = ByteArrayOutputStream()
val prevErr = System.err
System.setErr(PrintStream(outStream))
try {
body()
}
finally {
System.err.flush()
System.setErr(prevErr)
}
return outStream.toString()
}
private const val A_POM_FILE =
"""<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>a</groupId>
<artifactId>b</artifactId>
<version>0.0.1</version>
<packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>c</groupId>
<artifactId>d</artifactId>
<version>0.0.1</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
"""