Fix potential file handle leak in Attachment (#539)

* Make mockito available everywhere (core in particular).
* Also set the not-found path as FNFE message.
This commit is contained in:
Andrzej Cichocki 2017-04-12 15:30:28 +01:00 committed by GitHub
parent ac337240a6
commit 3e007c02f4
4 changed files with 53 additions and 3 deletions

View File

@ -481,8 +481,17 @@ interface UpgradedContract<in OldState : ContractState, out NewState : ContractS
* - Facts generated by oracles which might be reused a lot
*/
interface Attachment : NamedByHash {
fun open(): InputStream
fun openAsJAR() = JarInputStream(open())
fun openAsJAR(): JarInputStream {
val stream = open()
try {
return JarInputStream(stream)
} catch (t: Throwable) {
stream.use { throw t }
}
}
/**
* Finds the named file case insensitively and copies it to the output stream.
@ -501,6 +510,6 @@ interface Attachment : NamedByHash {
jar.closeEntry()
}
}
throw FileNotFoundException()
throw FileNotFoundException(path)
}
}

View File

@ -0,0 +1,41 @@
package net.corda.core.contracts
import com.nhaarman.mockito_kotlin.doAnswer
import com.nhaarman.mockito_kotlin.spy
import com.nhaarman.mockito_kotlin.whenever
import org.junit.Test
import java.io.ByteArrayOutputStream
import java.io.IOException
import java.util.jar.JarFile.MANIFEST_NAME
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
import kotlin.test.assertEquals
import kotlin.test.fail
class AttachmentTest {
@Test
fun `openAsJAR does not leak file handle if attachment has corrupted manifest`() {
var closeCalls = 0
val inputStream = spy(ByteArrayOutputStream().apply {
ZipOutputStream(this).use {
with(it) {
putNextEntry(ZipEntry(MANIFEST_NAME))
write(ByteArray(512)) // One byte above the limit.
}
}
}.toByteArray().inputStream()).apply { doAnswer { closeCalls += 1 }.whenever(this).close() }
val attachment = object : Attachment {
override val id get() = throw UnsupportedOperationException()
override fun open() = inputStream
}
try {
attachment.openAsJAR()
fail("Expected line too long.")
} catch (e: IOException) {
assertEquals("line too long", e.message)
}
assertEquals(1, closeCalls)
}
}

View File

@ -107,7 +107,6 @@ dependencies {
testCompile "junit:junit:$junit_version"
testCompile "org.assertj:assertj-core:${assertj_version}"
testCompile "com.pholser:junit-quickcheck-core:$quickcheck_version"
testCompile "com.nhaarman:mockito-kotlin:1.1.0"
testCompile project(':test-utils')
testCompile project(':client:jfx')

View File

@ -25,6 +25,7 @@ dependencies {
// Unit testing helpers.
compile "junit:junit:$junit_version"
compile "com.nhaarman:mockito-kotlin:1.1.0"
// Guava: Google test library (collections test suite)
compile "com.google.guava:guava-testlib:$guava_version"