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
Introduced detector for rule VNA-00 and VNA-02 with test cases #2077
base: master
Are you sure you want to change the base?
Conversation
Sorry for the big PR, but these two rules are really in a close connection with each other, so it made more sense for me to develop them together. |
Hello, this is not a proper review because all of this a above my pay-grade but here are a couple of comments and questions:
|
...ts/src/test/java/edu/umd/cs/findbugs/detect/BadVisibilityOnSharedPrimitiveVariablesTest.java
Outdated
Show resolved
Hide resolved
Thank you for your remarks @gtoison, I really appreciate them!
|
@ThrawnCA could you review this again please? |
...ts/src/test/java/edu/umd/cs/findbugs/detect/BadVisibilityOnSharedPrimitiveVariablesTest.java
Outdated
Show resolved
Hide resolved
...ts/src/test/java/edu/umd/cs/findbugs/detect/FindCompoundOperationsOnSharedVariablesTest.java
Outdated
Show resolved
Hide resolved
spotbugs/src/main/java/edu/umd/cs/findbugs/detect/BadVisibilityOnSharedPrimitiveVariables.java
Outdated
Show resolved
Hide resolved
spotbugs/src/main/java/edu/umd/cs/findbugs/detect/CompoundOperationsOnSharedVariables.java
Outdated
Show resolved
Hide resolved
spotbugs/src/main/java/edu/umd/cs/findbugs/detect/CompoundOperationsOnSharedVariables.java
Show resolved
Hide resolved
spotbugsTestCases/src/java/multithreaded/sharedPrimitiveVariables/SynchronizedBlock.java
Outdated
Show resolved
Hide resolved
...rc/java/multithreaded/sharedPrimitiveVariables/SynchronizedBlockAndBadVisibilityOnField.java
Outdated
Show resolved
Hide resolved
spotbugsTestCases/src/java/multithreaded/sharedPrimitiveVariables/SynchronizedMethod.java
Outdated
Show resolved
Hide resolved
...c/java/multithreaded/sharedPrimitiveVariables/SynchronizedMethodAndBadVisibilityOnField.java
Outdated
Show resolved
Hide resolved
spotbugsTestCases/src/java/multithreaded/sharedPrimitiveVariables/VolatileField.java
Outdated
Show resolved
Hide resolved
@ThrawnCA thanks for the review, I pushed the fixes, please check again. |
spotbugs/src/main/java/edu/umd/cs/findbugs/detect/BadVisibilityOnSharedPrimitiveVariables.java
Outdated
Show resolved
Hide resolved
spotbugs/src/main/java/edu/umd/cs/findbugs/detect/CompoundOperationsOnSharedVariables.java
Outdated
Show resolved
Hide resolved
spotbugs/src/main/java/edu/umd/cs/findbugs/detect/CompoundOperationsOnSharedVariables.java
Outdated
Show resolved
Hide resolved
|
||
@Before | ||
public void setup() { | ||
SystemProperties.setProperty("ful.debug", "true"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is "ful"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume it stands for FindUnreleasedLock
, it is the system property that defines the DEBUG
flag in the class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it would be worth to comment it here, so later the codereader will know it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, IMO the tests shouldn't modify the state of the system, so it would be worth to set it back to the original setting after the tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does the FindUnreleasedLock
have to do with this test? Why do you need to set this value?
Hi @baloghadamsoftware! Let me know if you wish for that commit to be in this PR, and if so, how would you like to proceed. |
The github actions in my PR are a mistake, I did not write them and did not intend to put them into this PR. I only tried to address the comments that you got on your PR. So please continue your work. |
### Added | ||
* New detector `BadVisibilityOnSharedPrimitiveVariables` for new bug type `SPV_BAD_VISIBILITY_ON_SHARED_PRIMITIVE_VARIABLES` (See [SEI CERT rule VNA00-J](https://wiki.sei.cmu.edu/confluence/display/java/VNA00-J.+Ensure+visibility+when+accessing+shared+primitive+variables)) | ||
* New detector `CompoundOperationsOnSharedVariables` for new bug type `COSV_COMPOUND_OPERATIONS_ON_SHARED_VARIABLES` (See [SEI CERT rule VNA02-J](https://wiki.sei.cmu.edu/confluence/display/java/VNA02-J.+Ensure+that+compound+operations+on+shared+variables+are+atomic)) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is already an Added
section in Unreleased. Can you please merge the two?
|
||
@Before | ||
public void setup() { | ||
SystemProperties.setProperty("ful.debug", "true"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it would be worth to comment it here, so later the codereader will know it.
|
||
@Before | ||
public void setup() { | ||
SystemProperties.setProperty("ful.debug", "true"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, IMO the tests shouldn't modify the state of the system, so it would be worth to set it back to the original setting after the tests.
return; | ||
} | ||
|
||
if (seen == Const.IFGE || seen == Const.IFGT || seen == Const.IFLT || seen == Const.IFLE || seen == Const.IFNE || seen == Const.IFEQ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this and the conditions for the if
in line 92 are disjunct, it would be worth to have this in an else
block, so this if isn't evaluated unnecessarily.
} | ||
|
||
private boolean nameIsConstructor(String name) { | ||
return name.equals(Const.CONSTRUCTOR_NAME); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's better to compare to the const value to avoid NPE.
public static boolean implementsRunnable(JavaClass javaClass) { | ||
try { | ||
return Stream.of(javaClass.getAllInterfaces()) | ||
.anyMatch(ifc -> ifc.getClassName().equals(RUNNABLE_SIGNATURE)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's better to compare to the const value to avoid NPE.
|
||
LocalVariableTable lvt = method.getLocalVariableTable(); | ||
if (lvt != null && Stream.of(lvt.getLocalVariableTable()) | ||
.anyMatch(lv -> signatureIsFromAtomicPackage(lv.getSignature()))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it would help the readability if you had the condition in a separate variable.
|
||
@Before | ||
public void setup() { | ||
SystemProperties.setProperty("ful.debug", "true"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO the tests shouldn't modify the state of the system, so it would be worth to set it back to the original setting after the tests.
return Stream.of(classToCheck.getMethods()).anyMatch(method -> isMethodMultiThreaded(method, classContext)); | ||
} | ||
|
||
public static boolean implementsRunnable(JavaClass javaClass) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I can see, this function is only called from inside this class. Wouldn't it be better to restrict the visibility?
return hasMultiThreadedInstruction(methodGen); | ||
} | ||
|
||
public static boolean hasMultiThreadedInstruction(MethodGen methodGen) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I can see, this function is only called from inside this class. Wouldn't it be better to restrict the visibility?
return false; | ||
} | ||
|
||
public static boolean isConcurrentLockInterfaceCall(String methodName) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I can see, this function is only called from inside this class. Wouldn't it be better to restrict the visibility?
Introducing new detector for SEI CERT rules:
The detectors looks for classes that could be part of multithreaded code. This means that the detector only analyzes classes, if either of the following conditions are true for the context of the class:
java.lang.Runnable
interface (this includes extending thejava.lang.Thread
class as well, due to transitive cheking for theRunnable
interface)synchronized
method or blockvolatile
oratomic
type variables (the latter means thejava.util.concurrent.atomic
package)java.util.concurrent.locks.Lock
interface call anywhere in it (lock()
,trylock()
,unlock()
)If any of the above mentioned conditions are present, then the VNA00 detector looks for primitive variables that match all of the following conditions:
volatile
, nor as an atomic type (java.util.concurrent.atomic
package)java.util.concurrent.locks.Lock
interface call:lock()
,trylock()
,unlock()
)If any of the above mentioned conditions are present, then the VNA02 detector looks for primitive variables that match all of the following conditions:
java.util.concurrent.atomic
package), important that volatile is not a guarantee in this rulejava.util.concurrent.locks.Lock
interface call:lock()
,trylock()
,unlock()
)Both detectors were tested against the code of the following repositories:
I provieded unit tests for each detectors, that covers all possible test cases (multiple types of multithreaded classes, every kind of compund operations for VNA02 etc.).
Although the numbers of the found bugs were high (specially in the case of Jenkins), all bugs seemed to be a possible vulnerability described by the VNA00 or VNA02 rules.