I have a jenkins plugin which contains code like this:
public int getLastBuildNumber() {
if (project != null && project.getLastBuild() != null ) {
return project.getLastBuild().getNumber();
}
return 0;
}
When I publish the code with mvn release:prepare release:perform -Dusername=myusername -Dpassword=mypassword, I got a bug saying Possible null pointer dereference.
Here's the result of mvn findbugs:gui:
Why does it say The return value from a method is dereferenced without a null check?
I think project != null && project.getLastBuild() != null is the null check, isn't it?
Is this a bug of findbugs? How can I solve it? Or can I disable findbugs when releasing my jenkins plugin?
You can visit here for the full code.
Unless your Project class is immutable or (at least) the value returned by getLastBuild() is a final field, your null-checks are not enough.
That's because, in theory, some other thread may call project.setLastBuild(null) just before your return statement:
if (project != null && project.getLastBuild() != null) {
// thread T does project.setLastBuild(null) here -- for whatever reason
return project.getLastBuild().getNumber(); // NPE!
}
To make this bullet proof, you need to move away from those moving parts and make your own local copies (synchronization is hardly an option in this case, imho):
LastBuild lastBuild = project != null ? project.getLastBuild() : null; // this only works as long as your project reference is final
return lastBuild != null ? lastBuild.getNumber() : 0;
Or, even better, make use of the Java8 Optional to perform all the necessary null-checks (implicitly) in one go:
return Optional.ofNullable(project)
.map(Project::getLastBuild)
.map(LastBuild::getNumber)
.orElse(0);
Related
(1) If a result of IMoniker::BindToObject is S_OK then returned pointer is valid. But PVS-Studio marks it as V595. Why?
(2) If QueryInterface is succeeded then returned pointer is valid. But PVS-Studio marks it as V595. Why?
HRESULT sc;
if (featureValidateSource)
{
sc = lpmk->BindToObject(lpbc, NULL, IID_IOleObject, (void**)&lpObject);
if (FAILED(sc))
{
lpbc->Release();
lpmk->Release();
if (lpObject) lpObject->Release();
return sc;
}
lpObject->GetUserClassID(&clsid); // (1) <<< V595
}
LPOLELINK lpOleLink;
if (SUCCEEDED(m_pObject->QueryInterface(IID_IOleLink,(void**)&lpOleLink)))
{
sc = lpOleLink->SetSourceMoniker(lpmk, clsid); // (2) <<< V595
}
...
if (lpObject != NULL) // (1) <<< V595
{
lpObject->Update();
lpObject->Release();
}
if (lpOleLink) // (2) <<< V595
{
lpOleLink->Release();
}
This is a fault of our function annotation system. PVS-Studio analyzer currently has annotations for over 6000 functions from the most popular libraries. These annotations allow the tool to perform a lot of diagnostics. However, we haven't yet annotated the functions BindToObject and QueryInterface. But even if we had, it wouldn't have helped. There are no annotations currently specifying how a returned poitner is related to the status of type HRESULT. There must be a connection: if certain functions have executed successfully, then non-null pointers are returned. There is no such thing now, but we'll gradually implement this algorithm. Then the false positives will go away.
Since there is no such connection now, the analyzer views the code in the following way:
if (X)
{
GetPtr(&ptr1);
if (Y)
return;
ptr1->foo(); // (1) <<< V595
}
if (GetPtr(&ptr2))
{
ptr2->foo(); // (2) <<< V595
}
if (ptr1 != NULL) // (1) <<< V595
;
if (ptr2 != NULL) // (1) <<< V595
;
The pointers are initialized somehow. After that, they are dereferenced and then checked for NULL. It looks suspicious, so the analyzer issues the warning.
So, yes, there is a fault on our part. We'll improve analysis of such constructs in time. Thank you for pointing this code out.
As for now, we suggest using one of the means of false positive suppression or use suppression base.
I often do something like this:
if (task != null && !task.IsCompleted && !task.IsCanceled && !task.IsFaulted)
{
// do something, e.g. cancel the task
}
It would be great to have task.IsPending as a shortcut for !task.IsCompleted && !task.IsCanceled && !task.IsFaulted, but it's not there. And task.Status == TaskStatus.Running is not the same, as task can be in one of the waiting states.
I have a custom Task extension method for this, but I'm curious why it is not there in the first place. Is checking for pending status this way considered somehow deprecated?
I think you're just looking for:
if (task != null && !task.IsCompleted)
As documented, IsCompleted covers faulted and canceled states as well as RanToCompletion:
IsCompleted will return true when the task is in one of the three final states: RanToCompletion, Faulted, or Canceled.
I'm looking at the following code from Programming Interviews Exposed, and I can't seem to understand how exactly it works. Won't this method always return null?
// Overload it to handle nodes as well
Node findLowestCommonAncestor( Node root, Node child1,
Node child2 ){
if( root == null || child1 == null || child2 == null ){
return null;
}
return findLowestCommonAncestor( root, child1.getValue(),
child2.getValue() );
}
From the code snippet, we don't really know what getValue returns. So if there are other overloaded versions of findLowestCommonAncestor, and getValue returns something other than Node, then the call to findLowestCommonAncestor in your snippet is not recursively calling itself.
I have a problem with code contracts and linq. I managed to narrow the issue to the following code sample. And now I am stuck.
public void SomeMethod()
{
var list = new List<Question>();
if (list.Take(5) == null) { }
// resharper hints that condition can never be true
if (list.ForPerson(12) == null) { }
// resharper does not hint that condition can never be true
}
public static IQueryable<Question> ForPerson(this IQueryable<Question> source, int personId)
{
if(source == null) throw new ArgumentNullException();
return from q in source
where q.PersonId == personId
select q;
}
What is wrong with my linq chain? Why doesn't resharper 'complain' when analyzing the ForPerson call?
EDIT: return type for ForPerson method changed from string to IQueryable, which I meant. (my bad)
Reshaper is correct that the result of a Take or Skip is never null - if there are no items the result is an IEnumerable<Question> which has no elements. I think to do what you want you should check Any.
var query = list.Take(5);
if (!query.Any())
{
// Code here executes only if there were no items in the list.
}
But how does this warning work? Resharper cannot know that the method never returns null from only looking at the method definition, and I assume that it does not reverse engineer the method body to determine that it never returns null. I assume therefore that it has been specially hard-coded with a rule specifying that the .NET methods Skip and Take do not return null.
When you write your own custom methods Reflector can make assumptions about your method behaviour from the interface, but your interface allows it to return null. Therefore it issues no warnings. If it analyzed the method body then it could see that null is impossible and would be able to issue a warning. But analyzing code to determine its possible behaviour is an incredibly difficult task and I doubt that Red Gate are willing to spend the money on solving this problem when they could add more useful features elsewhere with a much lower development cost.
To determine whether a boolean expression can ever return true is called the Boolean satisfiability problem and is an NP-hard problem.
You want Resharper to determine whether general method bodies can ever return null. This is a generalization of the above mentioned NP-hard problem. It's unlikely any tool will ever be able to do this correctly in 100% of cases.
if(source == null) throw new ArgumentNullException();
That's not the code contract way, do you instead mean:
Contract.Require(source != null);
Im making firefox extension. One function stores value in every tab, to use it later by other function.
function setValue(value) {
var attr = gBrowser.document.createAttribute("value");
attr.value = value;
gBrowser.document.attributes.setNamedItem(attr);
};
function getValue() {
var attr = gBrowser.document.attributes.getNamedItem("value");
if (attr != undefined && attr != null)
return attr.value;
else
return null;
};
For some reason, this doesn't work. Can you spot an error in my code?
Function getValue() should get value of active tab.
There are more errors than code here:
There's no gBrowser.document - you probably meant gBrowser.ownerDocument or just document (equivalent but simpler).
Neither is gBrowser.document.attributes, you meant gBrowser.attributes.
Using attributes seems very weird, an equivalent to the fixed up version of your code would be gBrowser.setAttribute("value", value) and gBrowser.getAttribute("value")
The fixed up code still isn't what you probably need and you didn't specify what exactly do you need (gBrowser.mCurrentTab.setAttribute?)