Commit d7db098a authored by Eric Bruneton's avatar Eric Bruneton
Browse files

Merge branch '317816-fix-class-reader-with-empty-file' into 'master'

Resolve "ClassReader constructor goes into infinite loop on zero length input streams"

Closes #317816

See merge request asm/asm!140
parents f01f998a cf523596
......@@ -85,6 +85,10 @@ import java.util.stream.Stream;
*/
public abstract class AsmTest {
/** The size of the temporary byte array used to read class input streams chunk by chunk. */
private static final int INPUT_STREAM_DATA_CHUNK_SIZE = 4096;
/** The name of JDK9 module classes. */
private static final String MODULE_INFO = "module-info";
/**
......@@ -436,7 +440,7 @@ public abstract class AsmTest {
try (InputStream inputStream = ClassLoader.getSystemResourceAsStream(resourceName)) {
assertNotNull(inputStream, "Class not found " + name);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] data = new byte[inputStream.available()];
byte[] data = new byte[INPUT_STREAM_DATA_CHUNK_SIZE];
int bytesRead;
while ((bytesRead = inputStream.read(data, 0, data.length)) != -1) {
outputStream.write(data, 0, bytesRead);
......
......@@ -87,6 +87,9 @@ public class ClassReader {
*/
static final int EXPAND_ASM_INSNS = 256;
/** The size of the temporary byte array used to read class input streams chunk by chunk. */
private static final int INPUT_STREAM_DATA_CHUNK_SIZE = 4096;
/**
* A byte array containing the JVMS ClassFile structure to be parsed. <i>The content of this array
* must not be modified. This field is intended for {@link Attribute} sub classes, and is normally
......@@ -262,7 +265,7 @@ public class ClassReader {
}
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] data = new byte[inputStream.available()];
byte[] data = new byte[INPUT_STREAM_DATA_CHUNK_SIZE];
int bytesRead;
while ((bytesRead = inputStream.read(data, 0, data.length)) != -1) {
outputStream.write(data, 0, bytesRead);
......
......@@ -31,11 +31,13 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.objectweb.asm.test.Assertions.assertThat;
import java.io.IOException;
import java.io.InputStream;
import java.time.Duration;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
......@@ -185,6 +187,27 @@ public class ClassReaderTest extends AsmTest implements Opcodes {
assertNotNull(classReader.getInterfaces());
}
/** Tests {@link ClassReader(java.io.InputStream)} with an empty stream. */
@Test
public void testStreamConstructorWithEmptyStream() throws IOException {
InputStream inputStream =
new InputStream() {
@Override
public int available() throws IOException {
return 0;
}
@Override
public int read() throws IOException {
return -1;
}
};
assertTimeoutPreemptively(
Duration.ofMillis(100),
() -> assertThrows(RuntimeException.class, () -> new ClassReader(inputStream)));
}
/** Tests the ClassReader accept method with a default visitor. */
@ParameterizedTest
@MethodSource(ALL_CLASSES_AND_ALL_APIS)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment