Skip to content

Added check to accept version 61, throw error for higher #521

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

Open
wants to merge 7 commits into
base: java-17
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -366,3 +366,11 @@ tasks.register('runPolDet', Exec) {
}

defaultTasks "buildJars"

sourceSets {
test {
resources {
srcDirs = ['src/tests/resources']
}
}
}
7 changes: 6 additions & 1 deletion src/main/gov/nasa/jpf/jvm/ClassFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public class ClassFile extends BinaryClassSource {
public static final int METHOD_HANDLE = 15;
public static final int METHOD_TYPE = 16;
public static final int INVOKE_DYNAMIC = 18;
private static final int MAX_SUPPORTED_VERSION = 61;

public static final int REF_GETFIELD = 1;
public static final int REF_GETSTATIC = 2;
Expand Down Expand Up @@ -218,7 +219,7 @@ public String getRequestedTypeName(){
public static final String BOOTSTRAP_METHOD_ATTR = "BootstrapMethods";

protected final static String[] stdClassAttrs = {
SOURCE_FILE_ATTR, DEPRECATED_ATTR, INNER_CLASSES_ATTR, DEPRECATED_ATTR, SIGNATURE_ATTR,
SOURCE_FILE_ATTR, DEPRECATED_ATTR, INNER_CLASSES_ATTR, SIGNATURE_ATTR,
RUNTIME_INVISIBLE_ANNOTATIONS_ATTR, RUNTIME_VISIBLE_ANNOTATIONS_ATTR, RUNTIME_VISIBLE_TYPE_ANNOTATIONS_ATTR,
ENCLOSING_METHOD_ATTR, BOOTSTRAP_METHOD_ATTR };

Expand Down Expand Up @@ -944,6 +945,10 @@ public void parse( ClassFileReader reader) throws ClassParseException {
// we don't do much with the version numbers yet
int minor = readU2();
int major = readU2();
if (major > MAX_SUPPORTED_VERSION) {
// this will throw ClassParseException if the major version java 18 or higher
error("Unsupported class file version: " + major);
}

// get the const pool
int cpCount = readU2();
Expand Down
50 changes: 50 additions & 0 deletions src/tests/gov/nasa/jpf/jvm/FileVersionTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package gov.nasa.jpf.jvm;

import gov.nasa.jpf.util.test.TestJPF;
import gov.nasa.jpf.vm.ClassParseException;
import org.junit.Test;

import java.io.*;

public class FileVersionTest extends TestJPF {

private static final String JAVA17_CLASS = "/TestClassJava17.class";
private static final String JAVA21_CLASS = "/TestClassJava21.class";

// loading a .class file into a byte array
private byte[] loadClassFile(String resourceName) throws IOException {
try (InputStream is = getClass().getResourceAsStream(resourceName)) {
if (is == null) throw new IOException("Resource not found: " + resourceName);

ByteArrayOutputStream bos = new ByteArrayOutputStream();
// we choose here buffer size 1024 cause its enough to read most .class files in one or two iterations
// smaller buffer size like 256 will require more operations and larger buffers will waster memory
// i'm not sure which is suitable for this since the test classes we complied is empty but i think both could work
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
bos.write(buffer, 0, bytesRead);
}
return bos.toByteArray();
}
}


@Test
public void testSupportedVersionJava17() throws IOException, ClassParseException {
byte[] classData = loadClassFile(JAVA17_CLASS);
ClassFile classFile = new ClassFile(classData);
ClassFileReader reader = new ClassFileReaderAdapter();
// this should pass with no exceptions
classFile.parse(reader);
}

@Test(expected = ClassParseException.class)
public void testUnsupportedVersionJava21() throws IOException, ClassParseException {
byte[] classData = loadClassFile(JAVA21_CLASS);
ClassFile classFile = new ClassFile(classData);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please enable this test and ensure it throws an exception. The test looks good; what was the reason for commenting it out? Perhaps JPF loads the version of the class file that was compiled by the build process rather than the one in src/tests, which would explain that this test does not throw an exception and thus fails?
In that case, try to find a way to make your manually uploaded class file take precedence in the class loader.

ClassFileReader reader = new ClassFileReaderAdapter();
// this should throw ClassParseException
classFile.parse(reader);
}
}
Binary file added src/tests/resources/TestClassJava17.class
Binary file not shown.
Binary file added src/tests/resources/TestClassJava21.class
Binary file not shown.
Loading