Skip to content

added the static method check in INVOKESTATIC.java #501

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 1 commit into
base: master
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
44 changes: 24 additions & 20 deletions src/main/gov/nasa/jpf/jvm/bytecode/INVOKESTATIC.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014, United States Government, as represented by the
* Copyright (C) 2024, United States Government, as represented by the
* Administrator of the National Aeronautics and Space Administration.
* All rights reserved.
*
Expand All @@ -17,7 +17,6 @@
*/
package gov.nasa.jpf.jvm.bytecode;


import gov.nasa.jpf.vm.ClassInfo;
import gov.nasa.jpf.vm.ClassLoaderInfo;
import gov.nasa.jpf.vm.ElementInfo;
Expand All @@ -28,7 +27,6 @@
import gov.nasa.jpf.vm.ThreadInfo;
import gov.nasa.jpf.vm.Types;


/**
* Invoke a class (static) method
* ..., [arg1, [arg2 ...]] => ...
Expand Down Expand Up @@ -57,14 +55,13 @@ public String toPostExecString(){
StringBuilder sb = new StringBuilder();
sb.append(getMnemonic());
sb.append(' ');
sb.append( invokedMethod.getFullName());
sb.append(invokedMethod.getFullName());

if (invokedMethod.isMJI()){
sb.append(" [native]");
}

return sb.toString();

}

public StaticElementInfo getStaticElementInfo (){
Expand All @@ -88,28 +85,37 @@ public Instruction execute (ThreadInfo ti) {
if (callee == null) {
return ti.createAndThrowException("java.lang.NoSuchMethodException", cname + '.' + mname);
}

// Added the static method check here
if (!callee.isStatic()) {
//System.out.println("hererrrererererer");
// If the method is not static, throw an exception
return ti.createAndThrowException("java.lang.IncompatibleClassChangeError",
"Expected static method " + callee.getFullName());
}


// this can be actually different than (can be a base)
// This can be actually different than (can be a base)
ClassInfo ciCallee = callee.getClassInfo();

if (ciCallee.initializeClass(ti)) {
// do class initialization before continuing
// note - this returns the next insn in the topmost clinit that just got pushed
// Do class initialization before continuing
// Note - this returns the next insn in the topmost clinit that just got pushed
return ti.getPC();
}

if (callee.isSynchronized()) {
ElementInfo ei = ciCallee.getClassObject();
ei = ti.getScheduler().updateObjectSharedness(ti, ei, null); // locks most likely belong to shared objects
ei = ti.getScheduler().updateObjectSharedness(ti, ei, null); // Locks most likely belong to shared objects

if (reschedulesLockAcquisition(ti, ei)){
return this;
}
}

setupCallee( ti, callee); // this creates, initializes and pushes the callee StackFrame
setupCallee(ti, callee); // This creates, initializes, and pushes the callee StackFrame

return ti.getPC(); // we can't just return the first callee insn if a listener throws an exception
return ti.getPC(); // We can't just return the first callee insn if a listener throws an exception
}

@Override
Expand All @@ -119,7 +125,7 @@ public MethodInfo getInvokedMethod(){
} else {
// Hmm, this would be pre-exec, but if the current thread is not the one executing the insn
// this might result in false sharedness of the class object
return getInvokedMethod( ThreadInfo.getCurrentThread());
return getInvokedMethod(ThreadInfo.getCurrentThread());
}
}

Expand All @@ -130,10 +136,10 @@ public MethodInfo getInvokedMethod (ThreadInfo ti){
if (clsInfo != null){
MethodInfo callee = clsInfo.getMethod(mname, true);
if (callee != null){
ClassInfo ciCallee = callee.getClassInfo(); // might be a superclass of ci, i.e. not what is referenced in the insn
ClassInfo ciCallee = callee.getClassInfo(); // Might be a superclass of ci, i.e. not what is referenced in the insn

if (!ciCallee.isRegistered()){
// if it wasn't registered yet, classLoaded listeners didn't have a chance yet to modify it..
// If it wasn't registered yet, classLoaded listeners didn't have a chance yet to modify it..
ciCallee.registerClass(ti);
// .. and might replace/remove MethodInfos
callee = clsInfo.getMethod(mname, true);
Expand All @@ -145,7 +151,7 @@ public MethodInfo getInvokedMethod (ThreadInfo ti){
return invokedMethod;
}

// can be different thatn the ci - method can be in a superclass
// Can be different than the ci - method can be in a superclass
public ClassInfo getInvokedClassInfo(){
return getInvokedMethod().getClassInfo();
}
Expand All @@ -163,10 +169,9 @@ public int getArgSize () {
return argSize;
}


@Override
public String toString() {
// methodInfo not set outside real call context (requires target object)
// MethodInfo not set outside real call context (requires target object)
return "invokestatic " + cname + '.' + mname;
}

Expand All @@ -177,7 +182,7 @@ public Object getFieldValue (String id, ThreadInfo ti) {

@Override
public void accept(JVMInstructionVisitor insVisitor) {
insVisitor.visit(this);
insVisitor.visit(this);
}

@Override
Expand All @@ -187,7 +192,7 @@ public Instruction typeSafeClone(MethodInfo mi) {
try {
clone = (INVOKESTATIC) super.clone();

// reset the method that this insn belongs to
// Reset the method that this insn belongs to
clone.mi = mi;

clone.invokedMethod = null;
Expand All @@ -200,4 +205,3 @@ public Instruction typeSafeClone(MethodInfo mi) {
return clone;
}
}

47 changes: 47 additions & 0 deletions src/tests/gov/nasa/jpf/jvm/InvokeStaticTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package gov.nasa.jpf.jvm;

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

public class InvokeStaticTest extends TestJPF {

static class D {
// Initially static method
public static String m(String s) {
return s;
}
}

static class C {
public static void main(String[] args) {
int i = 123;
D.m("foobar"); // This is a valid static method call
System.out.println(i);
}
}

@Test
public void testInvokeStaticSuccess() {
// Test should pass if static method invocation works fine
if (verifyNoPropertyViolation()) {
C.main(new String[0]);
}
}

@Test
public void testInvokeStaticFailure() {
if (verifyUnhandledException("java.lang.IncompatibleClassChangeError")) {
// Simulate making D.m() non-static to trigger the error
DNonStatic d = new DNonStatic();
d.m("foobar"); // This should cause the failure because the method is now non-static
}
}

// Simulate a non-static version of class D for this test
static class DNonStatic {
// Non-static method, which should fail when invoked via INVOKESTATIC
public String m(String s) {
return s;
}
}
}
Loading