Why PMD basic rulesets does not capture null dereference? - java

I am using PMD Plug-in 3.2.6.v2009033006 . But the default rulesets in pmd is not captured possible null pointer exception .
Java Code
public class SignUp extends HttpServlet{
public void doGet(HttpServletRequest req , HttpServletResponse res){
String user = req.getParameter("user");
user.trim();
}
}
user.trim(); if the user variable is null it will be prone to null pointer exception . I checked my code with pmd but it will not indicate this ?
How can i capture this ? . Is there any custom pmd ruleset is available?
Is there any custom rulesets available for capturing this ?

PMD isn't the right tool for this. You should use FindBugs to catch such problems.
But even with FindBugs, you won't catch anything because the above code is perfectly reasonable, and doesn't have any bug, unless you know that getParameter("user") can return null, and that there is something better to do than throwing a NullPointerException in this case.
If such code triggered an error, basically every line of code which calls a method on an object returned by another method would trigger an error. FindBugs supports annotations that allows declaring that the caller of a method should always check for null on the result returned by this method. See http://findbugs.sourceforge.net/manual/annotations.html. But of course, for third-party code, you can't do anything (other than writing your own rules).

Related

How to disable "unnecessary test for null" warning in NetBeans 14?

Short Version
How do i disable the "unnecessary test for null" warning in NetBeans 14 IDE?
Long Version
NetBeans as a well-known bug 1 2 3 4 where it will erroneously tell you that a test for null is unnecessary. For example in the following code:
import javax.validation.constraints.NotNull;
private void doSomething(#NotNull Object o) {
if (o == null) return;
//...do more stuff...
}
The IDE thinks
because the o parameter was tagged as #NotNullo
it must be impossible for o to be null
so it must be that the if statement is unnecessary
This is demonstrably false
The #NotNull annotation is only an IDE hint, not a runtime guarantee.
just because an argument to a method is tagged as #NotNullable
does not mean it cannot be null
You can prove this to yourself by passing null to the doSomething method. (we can even write the test code so the IDE generates no hints or warnings at all!):
Object o = getTestValue();
doSomething(o);
private Object getTestValue()
{
Object o = null;
return o;
}
private void doSomething(#NotNull Object o) {
Objects.requireNonNull(value);
//...do more stuff...
}
And watch doSomething method fail - because o is null - even though it is tagged #NotNull.
Now, there may be other implementations of #NotNull, or other compilers that add runtime checks. I'm not talking about those. The NetBeans IDE 14 warning is wrong, so i need to disable it.
Research Effort
I tried clicking the lightbulb, to hopefully configure the warning:
but it only offers to configure null deference warnings - which i definitely want to keep.
I tried pressing Alt+Enter to bring up more options:
but nothing of value appears:
I tried to let it bring me to the area to configure the Null dereferncing hint:
but it definitely has nothing to do with *unnecessary test for null.
I tried searching for a hint or warning named "null":
but it's not there.
I tried searching for a hint or warning named "unnecessary":
but it's not there.
I tried searching for a hint or warning named "test":
but it's not there.
How to turn it off
Which brings me to my question:
given that NetBeans IDE 14 has no way to turn off "unnecessary test for null" warning
how do i turn off the "unnecessary test for null" warning in NetBeans IDE 14?
Bonus Reading
What does unnecessary test for null mean?
Netbeans tells me to remove null comparison, but that breaks my code ("First thing to note is: NetBeans is wrong")
BugZilla: Bug 226923 - Wrong warning 'the expression is never null'
Bugzilla: Bug 262707 - Add configuration of Nullable/NonNull annotations. Use FQNs or allow to exclude FQNs.
You can turn off the "Unnecessary test for null" warning using the Java annotation #SuppressWarnings("null"). That annotation is found in java.lang, and there is no need for an import.
The OpenJDK Javadoc for SuppressWarnings for JDK 17 states:
Indicates that the named compiler warnings should be suppressed in the
annotated element (and in all program elements contained in the
annotated element) ... As a matter of style, programmers should always
use this annotation on the most deeply nested element where it is
effective. If you want to suppress a warning in a particular method,
you should annotate that method rather than its class.
From the linked documentation to section 9.6.4.5 of the Java Language Specification, #SuppressWarnings appears to do exactly what you want, with my emphasis added:
9.6.4.5. #SuppressWarnings
Java compilers are increasingly capable of issuing helpful "lint-like"
warnings. To encourage the use of such warnings, there should be some
way to disable a warning in a part of the program when the programmer
knows that the warning is inappropriate.
Here's sample code, based on that in the OP:
package suppression;
import javax.validation.constraints.NotNull; // Jakarta EE 8
//import jakarta.validation.constraints.NotNull; // Jakarta EE 9
public class Suppression {
public static void main(String[] args) {
Suppression supp = new Suppression();
Object o = supp.getTestValue();
supp.doSomething(o);
supp.doSomething2(o);
}
Object getTestValue() {
Object o = null;
return o;
}
private void doSomething(#NotNull Object o) {
if (o == null) {
System.out.println("Object is null!");
}
}
#SuppressWarnings("null")
private void doSomething2(#NotNull Object o) {
if (o == null) {
System.out.println("Object is null!");
}
}
}
Here's a screenshot of that code in NetBeans 14 which shows:
The unwanted warning "Unnecessary test for null" is shown on line 22 in method doSomething().
The annotation #SuppressWarnings("null") on line 27 prevents the unwanted warning "Unnecessary test for null" being shown on line 30 in the otherwise identical method doSomething2().
The answer is: it cannot be done.
NetBeans provides no way to disable the unnecessary test for null warning.
Workaround
As other people in other answers have noted:
the value can be null
NetBeans is wrong thinking it cannot be null
The correct way to resolve the (incorrect) warning is to obfuscate the check for null.
Rather than calling:
if (customer == null) { ... }
Instead call:
if (Object.isNull(customer)) { ... }
It is the same thing; except this way NetBeans doesn't realize that you're testing the variable for null, and so doesn't warn you.

The exception "NoSuchMethodError" appears in a multi module project of maven [duplicate]

On my current project, I've felt the need to create a sort of simulated callback system in Java using reflection. However, I'm having issues getting my reflection to actually function. The code at fault follows:
public Callback(Object parentObj, String methodName, Class<?>...parameters)
{
if(parentObj == null)
throw new IllegalArgumentException("parentObj cannot be null", new NullPointerException());
Class<?> clazz = parentObj.getClass();
// Trace debugging, see output
for(Method m : clazz.getDeclaredMethods())
if(m.getName().equals("myMethod")) System.out.println (m);
try { this.method = clazz.getMethod(methodName, parameters); }
catch(NoSuchMethodException nsme) { nsme.printStackTrace(); } // Exception caught
catch(SecurityException se) { se.printStackTrace(); }
this.parentObj = parentObj;
this.parameters = parameters;
}
When I construct the Callback object, I'm using syntax like this:
new Callback(this, "myMethod", boolean.class)
When I try to create my pseudo-callback, it hits the NoSuchMethodException catch block. I've included some trace debugging above to show the output of one of my methods failing. The output:
private void my.package.MyClass.myMethod(boolean)
java.lang.NoSuchMethodException: my.package.MyClass.myMethod(boolean)
at java.lang.Class.getMethod(Class.java:1605)
at my.package.other.Callback.<init>(Callback.java:63)
I couldn't figure the problem out, so I started hunting, to little avail. The best I could find was mention of versioning conflict between the compiled JAR and the runtime. However, MyJar.jar/META-INF/MANIFEST.MF contains Created-By: 1.6.0_02 (Sun Microsystems Inc.). My IDE is running C:\Program Files\Java\jdk1.6.0_02\bin\javac.exe to compile my project. I'm using C:\Program Files\Java\jdk1.6.0_02\bin\java.exe to run my JAR.
I'm at a loss why Class.getMethod is claiming the method doesn't exist, but Class.getMethods seems to have no problem finding it. Help? :(
Your method is private but getMethod() only returns public method.
You need to use getDeclaredMethod().
You need the parameter list to be absolutely correct for the method you want for the call to succeed.
I've found that tiny steps are important when doing reflection because the compiler doesn't help. Write a small snippet which actually invokes exactly the method you want to in this particular case, and then when that works, generalize it into the framework here. I would focus on the parameters passed.
The Javadoc for getMethod isn't explicit, but it looks like it might throw a NoSuchMethodException for methods that aren't public, and your method is private.
The versioning issue that can cause NoSuchMethodException isn't a difference between the compiler versions. It's a difference in the version of (in your case) MyClass at compile time versus runtime.
Since you're using reflection you issue might have nothing to do with versioning, though. Certainly that would not explain different behavior between getMethod and getDeclaredMethods, because you're running them against the same Class instance, hence a version difference isn't really possible.
Are you sure that the parameters match your actual method?

AndroidStudio (IDEA) code inspection: "... may produce NullPointerException"

I have following piece of code in Java:
String func() {
Object data = otherFunc();
return data.toString();
}
The otherFunc() is #Nullable function and it can return null. So the IDE highlights toString() method as dangerous, because it can cause NullPointerException.
But in my case, I'm 100% confident about not-null result of otherFunc(). So I added an assert condition there:
String func() {
Object data = otherFunc();
MyAssert.notNull(data, some_debug_info);
return data.toString();
}
There is a null-check verification inside the MyAssert.notNull() call and throwing an exception (with some additional debug info) if it's null.
Android Studio highlights toString() anyway...
Question:
How can I indicate that "data" object can't be null after the MyAssert.notNull() call? Maybe with some #annotations?
There are many similar places in the code, so the solution should modify the assert function only!
IntelliJ's Contract annotations might be what you're looking for.
Annotating your method with #Contract("null, _ -> fail") should tell intelliJ that entering null as the first parameter would cause an exception, meaning any code after the call will assume it is non-null.

TestNG classes expecting Exception.class

I have inherited some code from another team which uses
#Test (expectedExceptions = {Exception.class})
everywhere when the code might be throwing a more specific exception.
My understanding is that this is wrong because we are not expecting the right type of exception. But the current owners are saying that they have seen no issue because of this.
Is my understanding correct?
This is poor design, since it could be masking errors other than the one being tested for. As an example, suppose your code should throw a SecurityException on some operation but instead is throwing a NullPointerException because of a naive dereference. Your test would pass when it should fail.
You should always make your matchers as specific as possible, and in this case, that means the most specific exception class that applies.
Exception is Parent class of all types of exception in java, so basically your test will pass if code throws any checked or unchecked exception. But its better to write unit test that will expect a particular type of exception which your code can throw. For e.g. let say your have a method to validateParam
public void validateParam(String param) throws SomeCustomValidationException {
//suppose param is null , now this code will throw NullPointerException
if (param.length() > 2) {throw new SomeCustomValidationException();}
}
and you call it like this
public void businessLogic(String param) {
try {validateParam(param);}
catch(SomeCustomValidationException e){//show error dialog to the user}
}
So although your unit test will pass but your business logic will not work as you expected

FIndbug not identifying null pointer exception

I am using Findbugs integerated with eclipse.
When I run findbugs on my project the below code is not captured for possible null pointer exception.
In the below snippet the object test is prone to null pointer exception which is not identified by findbugs.
#Override
public boolean saveIrr(TestObject test) throws DuplicateRecordException {
boolean status = false
try {
test.getAddDate();
status = adhocMaintPopupMapper.saveIrr(IRRPopupMaint);
} catch (DataIntegrityViolationException e) {
logger.error("Error in Saving!", e);
throw new TransactionDataException("Error in Saving!", e);
}
return status;
}
Is there any configuration change required to make findbugs to identify this?
If you add #Nonnull to the parameter declaration, FindBugs will highlight anywhere you're passing a value that isn't checked for null. If you mark it #CheckForNull, FindBugs will highlight anywhere in the method that you access it without checking for null.
Which you do depends on the method's contract: does it tolerate null or not? Looking at its implementation it does not allow for null without throwing an unexpected exception. Therefore, test should be marked #Nonnull so you can spot incorrect calls.
Update
FindBugs will only check fields, parameters, method return values that are annotated with either #Nonnull or #CheckForNull. Anything without an annotation is assumed #Nullable which tells FindBugs to ignore it.
public boolean saveIrr(#Nonnull TestObject test) { ... }
public void dontCareAboutNull(TestObject value) {
saveIrr(value); // no bug
}
public void mightBeNull(#CheckForNull TestObject value) {
saveIrr(value); // bug
}
For this reason, we apply #Nonnull to all three types of values at the package level. Any value that needs to allow null must be annotated with #CheckForNull. We do not allow the use of #Nullable except in very few corner cases (e.g. #Autowired fields which Spring enforces).
I noticed that you're missing a ; in your code after "boolean status = false", this could be the reason why findbug has problems to parse your code.
OK from what I understood : you want to identify that test has not beeing tested for null. As far as I know there is no way to configure findbugs for doing this. Findbugs can warn you in 2 other cases :
- NP_ARGUMENT_MIGHT_BE_NULL : if you call your method saveIrr with a and argument that has not been tested for null before.
- NP_NULL_INSTANCEOF : if findbug identified that your value is guaranteed to be null at a point.
You can check all the Null Pointer warnings here they are identified with NP: http://findbugs.sourceforge.net/bugDescriptions.html
I think that such a warning would result in a too huge amount of bugs detected : all methods with arguments would give warnings for arguments that would be used before beeing tested.
What you can do is use the annotions of findbugs/jsr305. So if you add #Nullable to the getDate() method in TestObject it may trigger a NP warning. If you want to use those annotions be sure that the jsr305.jar is in your classpath...

Categories

Resources