Skip to content
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

Master #510

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open

Master #510

wants to merge 8 commits into from

Conversation

sanidhya00081
Copy link

Integrated a mechanism to detect and prevent invalid INVOKESTATIC calls by validating method properties during runtime in JPF (line 274).
Optimized the test pipeline by using Gradle-native methods to manage input-output dependencies, ensuring task portability and proper execution order.

Copy link
Member

@cyrille-artho cyrille-artho left a comment

Choose a reason for hiding this comment

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

I think there is a typo, please fix it so we can try the CI build/test again.

build.gradle Outdated Show resolved Hide resolved
@sanidhya00081
Copy link
Author

yeah sure @cyrille-artho

@sanidhya00081
Copy link
Author

Could you suggest me any changes, according to the errors the code encountered. @cyrille-artho

@cyrille-artho
Copy link
Member

Thanks! The build file works now, but one of the paths seems to be wrong, and D.java is missing in your PR, so it can't be found:

 - Property '$1' specifies file '/home/runner/work/jpf-core/jpf-core/src/main/java/D.java' which doesn't exist.

See the full log here: https://github.com/javapathfinder/jpf-core/actions/runs/12714274234/job/35472592178?pr=510

@sanidhya00081
Copy link
Author

Thanks for quoting the issue @cyrille-artho . I would be working on the on some amendments and would come up with a new PR.

@sanidhya00081
Copy link
Author

Hey! @cyrille-artho could this issue be assigned to me?

@cyrille-artho
Copy link
Member

Hey! @cyrille-artho could this issue be assigned to me?

This is a PR, not an issue. I can assign an issue to you once you have made a successful PR.

This version works better than the previous one, but it still results in build failures:

  - Property '$1' specifies file '/home/runner/work/jpf-core/jpf-core/src/main/java/D.java' which doesn't exist.
    
    Reason: An input file was expected to be present but it doesn't exist.
    
    Possible solutions:
      1. Make sure the file exists before the task is called.
      2. Make sure that the task which produces the file is declared as an input.
    
    For more information, please refer to https://docs.gradle.org/8.4/userguide/validation_problems.html#input_file_does_not_exist in the Gradle documentation.
  - Gradle detected a problem with the following location: '/home/runner/work/jpf-core/jpf-core/build/classes/java/main'.
    
    Reason: Task ':createJpfClassesJar' uses this output of task ':modifyAndCompileD' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.
    
    Possible solutions:
      1. Declare task ':modifyAndCompileD' as an input of ':createJpfClassesJar'.
      2. Declare an explicit dependency on ':modifyAndCompileD' from ':createJpfClassesJar' using Task#dependsOn.
      3. Declare an explicit dependency on ':modifyAndCompileD' from ':createJpfClassesJar' using Task#mustRunAfter.

I can see that jpf-core appears twice in a row in the path above (jpf-core/jpf-core), which is probably the reason the file is not found.
Gradle build dependency rules have changed a bit recently, so try to see if explicit dependency declarations fix the build.
Make sure that the Gradle build is successful on your system, as this will accelerate the CI/review cycle.

corrected the paths of C.java and D.java
Added explicit dependencies in compileTestJava, compileModules, createJpfClassesJar
@sanidhya00081
Copy link
Author

The build was successful on my system @cyrille-artho

Screenshot 2025-01-13 004539

@cyrille-artho
Copy link
Member

Great! I can confirm that the new build now works. This resolves the most difficult step.
To completen the work on issue #250, we need two more things:

  1. A test case that demonstrates that JPF incorrectly allows a static call to a non-static method to be executed, even though the "static" keyword had been removed and the file recompiled. You can find out how to write tests to run inside JPF on the wiki: https://github.com/javapathfinder/jpf-core/wiki/Writing-JPF-tests
  2. A fix that adds an additional check for the "static" flag in the method and correctly rejects such a call.

@sanidhya00081
Copy link
Author

@cyrille-artho Thanks!! I would surely be working on these two points and will revert back in a day.

checks whether JPF incorrectly allows a static call to a non-static method.
The test has passed and the build was successful.
@sanidhya00081
Copy link
Author

I have created the test file and have successfully checked whether JPF incorrectly allows a static call to a non-static method. The build was successful. @cyrille-artho

@cyrille-artho
Copy link
Member

Hi,
Thank you for your first attempt at a test. Note that just because an instance is null, the call is still a dynamic call. Your test therefore does not test the right thing.
A call to a static method is generated by using the class name instead of an instance. Your example C.java does this. If you run C.main against a re-compiled D.java (where the keyword static has been removed), you get a very different exception:

Exception in thread "main" java.lang.IncompatibleClassChangeError: Expected static method 

So your test can try that and call C.main instead; C.main then calls D.m, and we get the exception. (You can also call D.m directly from your test, as your regular unit tests will be compiled against the original static version of D.m. So we don't need to keep C.java anymore.)

If you adapt the test, it should first fail, because JPF does not check the static flag properly at run time, so the call to D.m succeeds even if D has been recompiled with a dynamic method.

@cyrille-artho
Copy link
Member

I think it's a good idea to first try to get a "properly failing" test, so we are sure that the expected exception is checked against in the right way. After that, the one-line change in JPF to fix the test can easily be confirmed as valid by rerunning the test against the fix.

@sanidhya00081
Copy link
Author

@cyrille-artho Sure!! I would that and will revert back asap. I have understood the issue. Thank you @cyrille-artho for the clear guidance. It really makes easy for me to proceed towards next steps.

When I am rebuilding, the exception is caught and the test fails with the message.
@sanidhya00081
Copy link
Author

I have tested the failure case successfully and have made a PR to show it. But I am not able to get what can I do next. @cyrille-artho can you give me some suggestions.

Copy link
Member

@cyrille-artho cyrille-artho left a comment

Choose a reason for hiding this comment

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

Please remove temp. files and move the test files to the right place. You might not need C.java anymore. Furthermore, the tests no longer compile, so please check your build.

__test__ Outdated
@@ -0,0 +1 @@
***
Copy link
Member

Choose a reason for hiding this comment

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

Please remove any temporary files in the PR. Change the test so any such files are removed at the end of the test.

@@ -0,0 +1,8 @@
package gov.nasa.jpf;
Copy link
Member

Choose a reason for hiding this comment

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

These files should be in src/test.

Copy link
Member

Choose a reason for hiding this comment

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

Please remove this file (as it is no longer needed, we have src/test/.../D.java now.

@@ -0,0 +1,7 @@
class C {
Copy link
Member

Choose a reason for hiding this comment

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

Move to src/test.

@@ -0,0 +1,3 @@
class D {
Copy link
Member

Choose a reason for hiding this comment

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

Move to src/test.

@cyrille-artho
Copy link
Member

As of now, some test files need to be moved to src/test. D.java is not found in one case during compilation, causing it to fail. Please check:

/home/runner/work/jpf-core/jpf-core/src/tests/gov/nasa/jpf/StaticCallToNonStaticTest.java:13: error: cannot find symbol
                D.m(); // This should throw IncompatibleClassChangeError after D.java is recompiled without static
                ^
  symbol:   variable D
  location: class StaticCallToNonStaticTest

…emporary files.

Stored D.java in src/test.
Updated dependencies for JUNIT5.
The build was successful.
@sanidhya00081
Copy link
Author

@cyrille-artho I have made the suggested changes for cleaning up files and removing them at the end. Made some dependency changes in build.gradle. Updated StaticCallToNonStaticTest.java.

Copy link
Member

@cyrille-artho cyrille-artho left a comment

Choose a reason for hiding this comment

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

Great, you have almost all the points resolved. There are a few changes remaining, but I hope they will be easy to do. Please see my comments.

@@ -0,0 +1,8 @@
package gov.nasa.jpf;
Copy link
Member

Choose a reason for hiding this comment

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

Please remove this file (as it is no longer needed, we have src/test/.../D.java now.

src/test/C.java Outdated
@@ -0,0 +1,7 @@
class C {
Copy link
Member

Choose a reason for hiding this comment

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

I think this file can be deleted, as testStaticCallToNonStatic does not use it, and we don't need a standalone example; once testStaticCallToNonStatic works as intended, it is simple enough to copy this to main in an empty class if one wants a standalone program to run the test.

@Test
public void testStaticCallToNonStatic() {
// Create an instance of D
D instance = new D();
Copy link
Member

Choose a reason for hiding this comment

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

Please remove.

// Expect IncompatibleClassChangeError when calling instance.m()
try {
System.out.println("Calling m() method");
instance.m(); // This should throw IncompatibleClassChangeError
Copy link
Member

Choose a reason for hiding this comment

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

This has to be D.m(); (like in C.java).


// Expect IncompatibleClassChangeError when calling instance.m()
try {
System.out.println("Calling m() method");
Copy link
Member

Choose a reason for hiding this comment

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

The println statement here can be deleted, as it is not desirable in a unit test to print to the console.

@cyrille-artho
Copy link
Member

Thank you very much! The process is mostly working now, but you accidentally changed the static to a dynamic call in the test; please see my comments.

Another thing I have not commented on, for some reason, this time, only one test (for your new feature) was run, rather than over 1000 tests. I don't know if this is due to change in the build/test process in build.gradle or due to caching by GitHub.

@cyrille-artho
Copy link
Member

Having now tried a clean clone with the test, I see that there is a problem with the new build dependencies.
I also think that the extra dependency is in the wrong order (it should be reversed):

tasks.named('compileTestJava') {
    dependsOn(copyLibs)
    dependsOn(copyResources)
    mustRunAfter(modifyAndCompileD)
}

We want compileTestJava to run before modifyAndCompileD, such that the code of the new test correctly compiles against the static method in D. Only after that, we recompile D.java, which will cause the test against D to fail.
Perhaps the dependency fix will again ensure that over 1000 unit tests (the entire test suite) is used.

Copy link
Member

@cyrille-artho cyrille-artho left a comment

Choose a reason for hiding this comment

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

Regarding build dependencies.

build.gradle Outdated
@@ -76,16 +114,20 @@ tasks.named('compilePeersJava') {
tasks.named('compileTestJava') {
dependsOn(copyLibs)
dependsOn(copyResources)
mustRunAfter(modifyAndCompileD)
Copy link
Member

Choose a reason for hiding this comment

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

I think this is reversed. I am not very familiar with the Gradle DSL, and the documentation is not 100 % clear, but this dependency and others (even some that have been declared previously) might be redundant or reversed. Please look at the dependencies and ensure that the original unit tests are preserved, so we have again over 1000 tests in the CI build/test.
You can check this by running ./gradlew clean test.

@sanidhya00081
Copy link
Author

@cyrille-artho I will work on the suggestions and will make changes ensuring that the original tests are preserved.

@sanidhya00081
Copy link
Author

sanidhya00081 commented Jan 18, 2025

@cyrille-artho If the method m() can be non-static, we need to create an instance of the D class

Deleted C.java
Removed instance statement with D.m()
Removed D.java from src/tests/gov/nasa/jpf/
D.java is in src/test
The build was successful
Updated dependency at line 116 in build.gradle, now that is not reversed I think.
@sanidhya00081
Copy link
Author

Hey @cyrille-artho I have made the suggested changes. I think now the issues is solved and the build was also successful. And the dependency issue is solved I think.

@cyrille-artho
Copy link
Member

Please try the build/test on your system before pushing:
Your new src/test/D.java is in the wrong place; the directory should be the same as the package name (src/test/pkg/name/D.java).
You also deleted two existing test files (StringConcatenationTest.java and another one); please reinstate them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants