This is an archive of the discontinued LLVM Phabricator instance.

[analyzer] Add generateErrorNode() APIs to CheckerContext
ClosedPublic

Authored by dcoughlin on Sep 10 2015, 3:47 PM.

Details

Summary

The analyzer trims unnecessary nodes from the exploded graph before reporting path diagnostics. However, in some cases it can trim all nodes (including the error node), leading to an assertion failure (see https://llvm.org/bugs/show_bug.cgi?id=24184).

This patch addresses the issue by adding two new APIs to CheckerContext to explicitly create error nodes. Unless the client provides a custom tag, these APIs tag the node with the checker's tag -- preventing it from being trimmed. The generateErrorNode() method creates a sink error node, while generateNonFatalErrorNode() creates an error node for a path that should continue being explored.

The intent is that one of these two methods should be used whenever a checker creates an error node.

I've updated the checkers to use these APIs. You'll notice that these APIs (unlike addTransition() and generateSink()) do not take an explicit Pred node. This is because I did not find any error nodes in the checkers that were created with an explicit node that was different than the default (the CheckerContext's Pred node). Do you think this is a reasonable simplification, or should we permit checkers to specify Pred explicitly?

I also added a test case written by Ying Yi as part of http://reviews.llvm.org/D12163 (that patch originally addressed this issue but was reverted because it introduced false positive regressions).

Diff Detail

Repository
rL LLVM

Event Timeline

dcoughlin updated this revision to Diff 34480.Sep 10 2015, 3:47 PM
dcoughlin retitled this revision from to [analyzer] Add generateErrorNode() APIs to CheckerContext.
dcoughlin updated this object.
dcoughlin added reviewers: zaks.anna, krememek.
dcoughlin added a subscriber: MaggieYi.
jordan_rose added inline comments.Sep 10 2015, 6:46 PM
include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
321 ↗(On Diff #34480)

What does "has made a mistake" mean? What is the mistake and how will they discover it?

zaks.anna added inline comments.Sep 10 2015, 6:46 PM
include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
229 ↗(On Diff #34480)

Most likely there are not much uses of this left and to avoid confusion we could require State and Pred inputs. What do you think?

244 ↗(On Diff #34480)

Please, use a non-null Pred for clarity

lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
89 ↗(On Diff #34480)

We should not generate a transition on an early exit here..

116 ↗(On Diff #34480)

Same here, no reason to generate a transition unless we are ready to report a bug. I'just pass C.generateNonFatalErrorNode() to llvm::make_unique<BugReport>.

lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
53 ↗(On Diff #34480)

Can this ever fail? In some cases we just assume it won't in others we tests..

Maybe it only fails when we cache out?

In general I like this change, the node handling of the checkers are more readable and reflects the intent in a clearer way. I have some comments inline.

include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
244 ↗(On Diff #34480)

The following workflow is not supported by this API: a checker that generates multiple transition in the same callback (the generated nodes are added sequentially to the path), and one of the might be an error node.

This also applies to generateNonFatalErrorNode.

In case we would like to improve the documentation it might be useful to give some pointers to the users which when should an error node be considered as fatal.

322 ↗(On Diff #34480)

As a slightly related note: is it documented anywhere what "cache out" means? Maybe it would be great to refer to that document or write it if it is not written yet.

jordan_rose added inline comments.Sep 11 2015, 12:30 PM
lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
53 ↗(On Diff #34480)

It does fail when we cache out, and I think we can still cache out if Pred has a different tag the second time around.

zaks.anna added inline comments.Sep 11 2015, 1:34 PM
include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
244 ↗(On Diff #34480)
  • We could introduce another API that requires a Pred node.
  • The workflow is supported right now by directly using addTransition API.
lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
53 ↗(On Diff #34480)

There some instances in this patch where we do not check if the returned node is null. We should be consistent.

dcoughlin marked 3 inline comments as done.Sep 11 2015, 4:05 PM
dcoughlin added inline comments.
include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
229 ↗(On Diff #34480)

There are 7 uses left. Requiring State and Pred seems like the right thing to me. I will change it.

321 ↗(On Diff #34480)

The mistake this guard protects against is adding a transition from a state to itself, which would normally cause a cache out. My understanding is that the whole point of this guard is to silently swallow that mistake. I found that surprising, which is why I added the comment.

lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
53 ↗(On Diff #34480)

Ok, I'll go through and add checks where they are missing.

zaks.anna added inline comments.Sep 11 2015, 4:09 PM
include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
321 ↗(On Diff #34480)

Should we add an assert here? I wonder if/how much it will get triggered.

dcoughlin updated this revision to Diff 34917.Sep 16 2015, 12:42 PM

Added checks for null generated error nodes in the few cases in checkers were they were missing and updated comments.

include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
321 ↗(On Diff #34480)

I tried adding an assert to the inverse of the 'if' condition here. The DereferenceChecker, CallAndMessageChecker, and DynamicTypePropagation all trigger it. Added a note about this in a comment.

322 ↗(On Diff #34480)

I've defined "cache out" in the comment.

lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
53 ↗(On Diff #34480)

There were 9 locations where checks for null error generated error nodes were missing. I added them.

zaks.anna accepted this revision.Sep 16 2015, 12:48 PM
zaks.anna edited edge metadata.
This revision is now accepted and ready to land.Sep 16 2015, 12:48 PM
xazax.hun added inline comments.Sep 16 2015, 1:10 PM
include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
328 ↗(On Diff #34917)

I think the most common form of relying on this branch is adding a transition to an unchanged state.

This revision was automatically updated to reflect the committed changes.

Did you forget to update examples/analyzer-plugin? Fixed in r247862.