This is an archive of the discontinued LLVM Phabricator instance.

MPI-Checker patch for Clang Static Analyzer
ClosedPublic

Authored by dcoughlin on Jun 7 2016, 9:16 AM.

Details

Summary

(Cloning the revision for the ASan issue since the old one is closed and can't be re-opened)

This patch adds a static analysis checker to verify the correct usage of the MPI API in C and C++.

3 path-sensitive checks are included:

  • Double nonblocking: Double request usage by nonblocking calls without intermediate wait
  • Missing wait: Nonblocking call without matching wait.
  • Unmatched wait: Waiting for a request that was never used by a nonblocking call

Examples of how to use the checker can be found on: GitHub https://github.com/0ax1/MPI-Checker

Diff Detail

Event Timeline

dcoughlin updated this revision to Diff 59899.Jun 7 2016, 9:16 AM
dcoughlin retitled this revision from to MPI-Checker patch for Clang Static Analyzer.
dcoughlin updated this object.
dcoughlin added a subscriber: cfe-commits.
dcoughlin edited edge metadata.Jun 7 2016, 9:23 AM

Alexander,

When I committed your patch, the AddressSanitizer bots found a memory corruption issue so I reverted it. This will need to be fixed before we can commit the patch. Since Phabricator automatically closed D12761, I've created a new revision. The attached diff is a very a slightly modified version of your original patch modified so that it compiles with gcc, which is more strict about certain template specializations and brace initializations.

Here is the ASan report. It looks to me like the issue is that MPIChecker is holding on a reference to a clang::ento::BugReporter after the lifetime of the BugReporter has ended. The BugReporter lives in ExprEngine and the analyzer creates a new ExprEngine for each top-level declaration that is analyzed but uses the same Checker instances across declarations. This means it is not safe to stash a reference to the BugReporter in an instance of MPIBugReporter in an instance of MPIChecker.

18751==ERROR: AddressSanitizer: stack-use-after-return on address 0x7f0c695ebc70 at pc 0x00000867b44c bp 0x7ffe3b01d6f0 sp 0x7ffe3b01d6e8

READ of size 8 at 0x7f0c695ebc70 thread T0

#0 0x867b44b in getSourceManager /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h:448:46
#1 0x867b44b in clang::ento::BugReporter::emitReport(std::__1::unique_ptr<clang::ento::BugReport, std::__1::default_delete<clang::ento::BugReport> >) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp:3240
#2 0x8636355 in clang::ento::mpi::MPIBugReporter::reportUnmatchedWait(clang::ento::CallEvent const&, clang::ento::MemRegion const*, clang::ento::ExplodedNode const*) const /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.cpp:82:3
#3 0x843e1ee in clang::ento::mpi::MPIChecker::checkUnmatchedWaits(clang::ento::CallEvent const&, clang::ento::CheckerContext&) const /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp:88:7
#4 0x8447dc8 in checkPreCall /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.h:36:5
#5 0x8447dc8 in void clang::ento::check::PreCall::_checkCall<clang::ento::mpi::MPIChecker>(void*, clang::ento::CallEvent const&, clang::ento::CheckerContext&) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h:168
#6 0x86db2f2 in operator() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h:59:12
#7 0x86db2f2 in runChecker /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp:269
#8 0x86db2f2 in expandGraphWithCheckers<(anonymous namespace)::CheckCallContext> /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp:123
#9 0x86db2f2 in clang::ento::CheckerManager::runCheckersForCallEvent(bool, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&, clang::ento::CallEvent const&, clang::ento::ExprEngine&, bool) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp:285
#10 0x8782a84 in runCheckersForPreCall /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h:252:5
#11 0x8782a84 in clang::ento::ExprEngine::evalCall(clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNode*, clang::ento::CallEvent const&) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp:509
#12 0x878205b in clang::ento::ExprEngine::VisitCallExpr(clang::CallExpr const*, clang::ento::ExplodedNode*, clang::ento::ExplodedNodeSet&) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp:487:5
#13 0x872a0d8 in clang::ento::ExprEngine::Visit(clang::Stmt const*, clang::ento::ExplodedNode*, clang::ento::ExplodedNodeSet&) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp:1104:7
#14 0x87210bf in clang::ento::ExprEngine::ProcessStmt(clang::CFGStmt, clang::ento::ExplodedNode*) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp:448:5
#15 0x87207ae in clang::ento::ExprEngine::processCFGElement(clang::CFGElement, clang::ento::ExplodedNode*, unsigned int, clang::ento::NodeBuilderContext*) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp:297:7
#16 0x86fc7a6 in clang::ento::CoreEngine::HandlePostStmt(clang::CFGBlock const*, unsigned int, clang::ento::ExplodedNode*) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp:515:5
#17 0x86fafed in clang::ento::CoreEngine::dispatchWorkItem(clang::ento::ExplodedNode*, clang::ProgramPoint, clang::ento::WorkListUnit const&) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp:274:7
#18 0x86f9891 in clang::ento::CoreEngine::ExecuteWorkList(clang::LocationContext const*, unsigned int, llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp:231:5
#19 0x67f1ab5 in ExecuteWorkList /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h:109:12
#20 0x67f1ab5 in (anonymous namespace)::AnalysisConsumer::ActionExprEngine(clang::Decl*, bool, clang::ento::ExprEngine::InliningModes, llvm::DenseSet<clang::Decl const*, llvm::DenseMapInfo<clang::Decl const*> >*) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:664
#21 0x67f0ae2 in RunPathSensitiveChecks /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:694:5
#22 0x67f0ae2 in (anonymous namespace)::AnalysisConsumer::HandleCode(clang::Decl*, unsigned int, clang::ento::ExprEngine::InliningModes, llvm::DenseSet<clang::Decl const*, llvm::DenseMapInfo<clang::Decl const*> >*) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:632
#23 0x67dc135 in HandleDeclsCallGraph /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:495:5
#24 0x67dc135 in (anonymous namespace)::AnalysisConsumer::HandleTranslationUnit(clang::ASTContext&) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:547
#25 0x687dae4 in clang::ParseAST(clang::Sema&, bool, bool) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Parse/ParseAST.cpp:167:3
#26 0x51c090b in clang::FrontendAction::Execute() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Frontend/FrontendAction.cpp:457:8
#27 0x510f614 in clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp:876:7
#28 0x537fa92 in clang::ExecuteCompilerInvocation(clang::CompilerInstance*) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:241:18
#29 0x8fc2f2 in cc1_main(llvm::ArrayRef<char const*>, char const*, void*) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/tools/driver/cc1_main.cpp:116:13
#30 0x8f6a88 in ExecuteCC1Tool /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/tools/driver/driver.cpp:301:12
#31 0x8f6a88 in main /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/tools/driver/driver.cpp:381
#32 0x7f0c6c208f44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21f44)
#33 0x816952 in _start (/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm_build_asan/bin/clang-3.9+0x816952)

Address 0x7f0c695ebc70 is located in stack of thread T0 at offset 1136 in frame

  #0 0x67f130f in (anonymous namespace)::AnalysisConsumer::ActionExprEngine(clang::Decl*, bool, clang::ento::ExprEngine::InliningModes, llvm::DenseSet<clang::Decl const*, llvm::DenseMapInfo<clang::Decl const*> >*) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:644

This frame has 5 object(s):
  [32, 184) 'P.i'
  [256, 260) 'FD.i'
  [272, 296) 'ref.tmp.i'
  [336, 344) 'agg.tmp.i'
  [368, 1248) 'Eng' <== Memory access at offset 1136 is inside this variable

HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext

(longjmp and C++ exceptions *are* supported)

SUMMARY: AddressSanitizer: stack-use-after-return /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h:448:46 in getSourceManager
Shadow bytes around the buggy address:

0x0fe20d2b5730: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x0fe20d2b5740: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x0fe20d2b5750: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x0fe20d2b5760: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x0fe20d2b5770: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5

>0x0fe20d2b5780: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5[f5]f5

0x0fe20d2b5790: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x0fe20d2b57a0: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x0fe20d2b57b0: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x0fe20d2b57c0: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x0fe20d2b57d0: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5

Shadow byte legend (one shadow byte represents 8 application bytes):

Addressable:           00
Partially addressable: 01 02 03 04 05 06 07 
Heap left redzone:       fa
Heap right redzone:      fb
Freed heap region:       fd
Stack left redzone:      f1
Stack mid redzone:       f2
Stack right redzone:     f3
Stack partial redzone:   f4
Stack after return:      f5
Stack use after scope:   f8
Global redzone:          f9
Global init order:       f6
Poisoned by user:        f7
Container overflow:      fc
Array cookie:            ac
Intra object redzone:    bb
ASan internal:           fe
Left alloca redzone:     ca
Right alloca redzone:    cb

18751==ABORTING


Testing: 0
FAIL: Clang :: Analysis/mpicheckernotes.cpp (317 of 9433)

lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.h
51

This is not safe because the lifetime of the BugReporter is shorter than the lifetime of the checker.

Instead, I would recommend creating a new instance of MPIBugReporter when reporting a bug. Since MPIBugReporter is only ever used when reporting bugs the cost of creating it each time (rather than caching it in an in instance variable) should not be an problem.

lib/StaticAnalyzer/Checkers/MPI-Checker/MPIFunctionClassifier.h
26

Can this be changed to take an ASTContext& instead?

Hi Devin,
thanks for fixing the GCC build errors and setting up the commit!

Unfortunately, creating an MPIBugReporter instance only when a bug occurs does cause a separate issue.
The instance seems to be freed, before the reports get flushed.

void MPIChecker::checkDoubleNonblocking(const CallEvent &PreCallEvent,
                                        CheckerContext &Ctx) const {
  if (!FuncClassifier->isNonBlockingType(PreCallEvent.getCalleeIdentifier())) {
    return;
  }
  const MemRegion *const MR =
      PreCallEvent.getArgSVal(PreCallEvent.getNumArgs() - 1).getAsRegion();
  if (!MR)
    return;
  const ElementRegion *const ER = dyn_cast<ElementRegion>(MR);

  // The region must be typed, in order to reason about it.
  if (!isa<TypedRegion>(MR) || (ER && !isa<TypedRegion>(ER->getSuperRegion())))
    return;

  ProgramStateRef State = Ctx.getState();
  const Request *const Req = State->get<RequestMap>(MR);

  // double nonblocking detected
  if (Req && Req->CurrentState == Request::State::Nonblocking) {
    ExplodedNode *ErrorNode = Ctx.generateNonFatalErrorNode();
    std::unique_ptr<MPIBugReporter> BReporter{new MPIBugReporter{ // <------------------------
        Ctx.getBugReporter(), *this, Ctx.getAnalysisManager().getASTContext()}};
    BReporter->reportDoubleNonblocking(PreCallEvent, *Req, MR, ErrorNode);
    Ctx.addTransition(ErrorNode->getState(), ErrorNode);
  }
  // no error
  else {
    State = State->set<RequestMap>(MR, Request::State::Nonblocking);
    Ctx.addTransition(State);
  }
}

Command Output (stderr):

55584==ERROR: AddressSanitizer: heap-use-after-free on address 0x60700000b540 at pc 0x00011391de54 bp 0x7fff51337e30 sp 0x7fff51337e28

READ of size 8 at 0x60700000b540 thread T0

#0 0x11391de53 in clang::ento::BugReporter::FlushReports() (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x105059e53)
#1 0x1126c561c in (anonymous namespace)::AnalysisConsumer::ActionExprEngine(clang::Decl*, bool, clang::ento::ExprEngine::InliningModes, llvm::DenseSet<clang::Decl const*, llvm::DenseMapInfo<clang::Decl const*> >*) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x103e0161c)
#2 0x1126c4c06 in (anonymous namespace)::AnalysisConsumer::HandleCode(clang::Decl*, unsigned int, clang::ento::ExprEngine::InliningModes, llvm::DenseSet<clang::Decl const*, llvm::DenseMapInfo<clang::Decl const*> >*) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x103e00c06)
#3 0x1126bf06a in (anonymous namespace)::AnalysisConsumer::HandleDeclsCallGraph(unsigned int) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x103dfb06a)
#4 0x1126bb50e in (anonymous namespace)::AnalysisConsumer::HandleTranslationUnit(clang::ASTContext&) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x103df750e)
#5 0x11273ea4b in clang::ParseAST(clang::Sema&, bool, bool) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x103e7aa4b)
#6 0x1119faf2f in clang::FrontendAction::Execute() (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x103136f2f)
#7 0x111962b04 in clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x10309eb04)
#8 0x111a7ba23 in clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x1031b7a23)
#9 0x10e8d3e8c  (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x10000fe8c)
#10 0x10e8c9116  (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x100005116)
#11 0x10e8c73d1  (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x1000033d1)

LLVMSymbolizer: error reading file: No object file for requested architecture

#12 0x7fff86f395ac  (/usr/lib/system/libdyld.dylib+0x35ac)
#13 0x8  (<unknown module>)

0x60700000b540 is located 0 bytes inside of 80-byte region [0x60700000b540,0x60700000b590)
freed by thread T0 here:

#0 0x11df36d1b in wrap__ZdlPv (/usr/local/lib/clang/3.8.1/lib/darwin/libclang_rt.asan_osx_dynamic.dylib+0x57d1b)
#1 0x1137dd0cf in clang::ento::mpi::MPIBugReporter::~MPIBugReporter() (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x104f190cf)
#2 0x1137db9a1 in clang::ento::mpi::MPIChecker::checkMissingWaits(clang::ento::SymbolReaper&, clang::ento::CheckerContext&) const (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x104f179a1)
#3 0x11398de38 in (anonymous namespace)::CheckDeadSymbolsContext::runChecker(clang::ento::CheckerFn<void (clang::ento::SymbolReaper&, clang::ento::CheckerContext&)>, clang::ento::NodeBuilder&, clang::ento::ExplodedNode*) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x1050c9e38)
#4 0x113982269 in void expandGraphWithCheckers<(anonymous namespace)::CheckDeadSymbolsContext>((anonymous namespace)::CheckDeadSymbolsContext, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x1050be269)
#5 0x113981f24 in clang::ento::CheckerManager::runCheckersForDeadSymbols(clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&, clang::ento::SymbolReaper&, clang::Stmt const*, clang::ento::ExprEngine&, clang::ProgramPoint::Kind) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x1050bdf24)
#6 0x1139c1bc7 in clang::ento::ExprEngine::removeDead(clang::ento::ExplodedNode*, clang::ento::ExplodedNodeSet&, clang::Stmt const*, clang::LocationContext const*, clang::Stmt const*, clang::ProgramPoint::Kind) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x1050fdbc7)
#7 0x1139fefb6 in clang::ento::ExprEngine::removeDeadOnEndOfFunction(clang::ento::NodeBuilderContext&, clang::ento::ExplodedNode*, clang::ento::ExplodedNodeSet&) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x10513afb6)
#8 0x1139d1d24 in clang::ento::ExprEngine::processEndOfFunction(clang::ento::NodeBuilderContext&, clang::ento::ExplodedNode*) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x10510dd24)
#9 0x1139a14db in clang::ento::CoreEngine::HandleBlockEdge(clang::BlockEdge const&, clang::ento::ExplodedNode*) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x1050dd4db)
#10 0x1139a0ea5 in clang::ento::CoreEngine::dispatchWorkItem(clang::ento::ExplodedNode*, clang::ProgramPoint, clang::ento::WorkListUnit const&) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x1050dcea5)
#11 0x1139a0198 in clang::ento::CoreEngine::ExecuteWorkList(clang::LocationContext const*, unsigned int, llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x1050dc198)
#12 0x1126c5c79 in clang::ento::ExprEngine::ExecuteWorkList(clang::LocationContext const*, unsigned int) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x103e01c79)
#13 0x1126c5599 in (anonymous namespace)::AnalysisConsumer::ActionExprEngine(clang::Decl*, bool, clang::ento::ExprEngine::InliningModes, llvm::DenseSet<clang::Decl const*, llvm::DenseMapInfo<clang::Decl const*> >*) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x103e01599)
#14 0x1126c4c06 in (anonymous namespace)::AnalysisConsumer::HandleCode(clang::Decl*, unsigned int, clang::ento::ExprEngine::InliningModes, llvm::DenseSet<clang::Decl const*, llvm::DenseMapInfo<clang::Decl const*> >*) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x103e00c06)
#15 0x1126bf06a in (anonymous namespace)::AnalysisConsumer::HandleDeclsCallGraph(unsigned int) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x103dfb06a)
#16 0x1126bb50e in (anonymous namespace)::AnalysisConsumer::HandleTranslationUnit(clang::ASTContext&) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x103df750e)
#17 0x11273ea4b in clang::ParseAST(clang::Sema&, bool, bool) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x103e7aa4b)
#18 0x1119faf2f in clang::FrontendAction::Execute() (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x103136f2f)
#19 0x111962b04 in clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x10309eb04)
#20 0x111a7ba23 in clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x1031b7a23)
#21 0x10e8d3e8c  (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x10000fe8c)
#22 0x10e8c9116  (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x100005116)
#23 0x10e8c73d1  (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x1000033d1)
#24 0x7fff86f395ac  (/usr/lib/system/libdyld.dylib+0x35ac)
#25 0x8  (<unknown module>)

previously allocated by thread T0 here:

#0 0x11df3675b in wrap__Znwm (/usr/local/lib/clang/3.8.1/lib/darwin/libclang_rt.asan_osx_dynamic.dylib+0x5775b)
#1 0x1137dc60b in clang::ento::mpi::MPIBugReporter::MPIBugReporter(clang::ento::BugReporter&, clang::ento::CheckerBase const&, clang::ento::mpi::MPIFunctionClassifier const&) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x104f1860b)
#2 0x1137db973 in clang::ento::mpi::MPIChecker::checkMissingWaits(clang::ento::SymbolReaper&, clang::ento::CheckerContext&) const (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x104f17973)
#3 0x11398de38 in (anonymous namespace)::CheckDeadSymbolsContext::runChecker(clang::ento::CheckerFn<void (clang::ento::SymbolReaper&, clang::ento::CheckerContext&)>, clang::ento::NodeBuilder&, clang::ento::ExplodedNode*) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x1050c9e38)
#4 0x113982269 in void expandGraphWithCheckers<(anonymous namespace)::CheckDeadSymbolsContext>((anonymous namespace)::CheckDeadSymbolsContext, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x1050be269)
#5 0x113981f24 in clang::ento::CheckerManager::runCheckersForDeadSymbols(clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&, clang::ento::SymbolReaper&, clang::Stmt const*, clang::ento::ExprEngine&, clang::ProgramPoint::Kind) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x1050bdf24)
#6 0x1139c1bc7 in clang::ento::ExprEngine::removeDead(clang::ento::ExplodedNode*, clang::ento::ExplodedNodeSet&, clang::Stmt const*, clang::LocationContext const*, clang::Stmt const*, clang::ProgramPoint::Kind) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x1050fdbc7)
#7 0x1139fefb6 in clang::ento::ExprEngine::removeDeadOnEndOfFunction(clang::ento::NodeBuilderContext&, clang::ento::ExplodedNode*, clang::ento::ExplodedNodeSet&) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x10513afb6)
#8 0x1139d1d24 in clang::ento::ExprEngine::processEndOfFunction(clang::ento::NodeBuilderContext&, clang::ento::ExplodedNode*) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x10510dd24)
#9 0x1139a14db in clang::ento::CoreEngine::HandleBlockEdge(clang::BlockEdge const&, clang::ento::ExplodedNode*) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x1050dd4db)
#10 0x1139a0ea5 in clang::ento::CoreEngine::dispatchWorkItem(clang::ento::ExplodedNode*, clang::ProgramPoint, clang::ento::WorkListUnit const&) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x1050dcea5)
#11 0x1139a0198 in clang::ento::CoreEngine::ExecuteWorkList(clang::LocationContext const*, unsigned int, llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x1050dc198)
#12 0x1126c5c79 in clang::ento::ExprEngine::ExecuteWorkList(clang::LocationContext const*, unsigned int) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x103e01c79)
#13 0x1126c5599 in (anonymous namespace)::AnalysisConsumer::ActionExprEngine(clang::Decl*, bool, clang::ento::ExprEngine::InliningModes, llvm::DenseSet<clang::Decl const*, llvm::DenseMapInfo<clang::Decl const*> >*) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x103e01599)
#14 0x1126c4c06 in (anonymous namespace)::AnalysisConsumer::HandleCode(clang::Decl*, unsigned int, clang::ento::ExprEngine::InliningModes, llvm::DenseSet<clang::Decl const*, llvm::DenseMapInfo<clang::Decl const*> >*) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x103e00c06)
#15 0x1126bf06a in (anonymous namespace)::AnalysisConsumer::HandleDeclsCallGraph(unsigned int) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x103dfb06a)
#16 0x1126bb50e in (anonymous namespace)::AnalysisConsumer::HandleTranslationUnit(clang::ASTContext&) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x103df750e)
#17 0x11273ea4b in clang::ParseAST(clang::Sema&, bool, bool) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x103e7aa4b)
#18 0x1119faf2f in clang::FrontendAction::Execute() (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x103136f2f)
#19 0x111962b04 in clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x10309eb04)
#20 0x111a7ba23 in clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x1031b7a23)
#21 0x10e8d3e8c  (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x10000fe8c)
#22 0x10e8c9116  (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x100005116)
#23 0x10e8c73d1  (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x1000033d1)
#24 0x7fff86f395ac  (/usr/lib/system/libdyld.dylib+0x35ac)
#25 0x8  (<unknown module>)

SUMMARY: AddressSanitizer: heap-use-after-free (/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/build/debug/./bin/clang+0x105059e53) in clang::ento::BugReporter::FlushReports()
Shadow bytes around the buggy address:

0x1c0e00001650: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c0e00001660: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c0e00001670: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c0e00001680: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c0e00001690: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa

>0x1c0e000016a0: fa fa fa fa fa fa fa fa[fd]fd fd fd fd fd fd fd

0x1c0e000016b0: fd fd fa fa fa fa fd fd fd fd fd fd fd fd fd fd
0x1c0e000016c0: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fa fa
0x1c0e000016d0: fa fa 00 00 00 00 00 00 00 00 00 fa fa fa fa fa
0x1c0e000016e0: 00 00 00 00 00 00 00 00 00 fa fa fa fa fa 00 00
0x1c0e000016f0: 00 00 00 00 00 00 00 fa fa fa fa fa 00 00 00 00

Shadow byte legend (one shadow byte represents 8 application bytes):

Addressable:           00
Partially addressable: 01 02 03 04 05 06 07 
Heap left redzone:       fa
Heap right redzone:      fb
Freed heap region:       fd
Stack left redzone:      f1
Stack mid redzone:       f2
Stack right redzone:     f3
Stack partial redzone:   f4
Stack after return:      f5
Stack use after scope:   f8
Global redzone:          f9
Global init order:       f6
Poisoned by user:        f7
Container overflow:      fc
Array cookie:            ac
Intra object redzone:    bb
ASan internal:           fe
Left alloca redzone:     ca
Right alloca redzone:    cb

55584==ABORTING

lib/StaticAnalyzer/Checkers/MPI-Checker/MPIFunctionClassifier.h
26

That works, I changed type to ASTContext.

Hi,

I now solved this, by using a small_vector of MPIBugReporters (MPIChecker.h line: 101).
So each time a report is generated, a new MPIBugReporter is added to that vector,
in order to refer to the correct ExprEngine and keep them available for the report flush.
I attached the updated patch, as part of this comment.

dcoughlin updated this revision to Diff 60472.Jun 12 2016, 11:40 AM
dcoughlin edited edge metadata.

Alexander, a drawback with using keeping a vector of MPIBugReporters in the checker is that this will essentially "leak" all the created bug reporters.

How about this instead:

  • Remove MPIBugReporter's MPIFunctionClassifier constructor parameter (it doesn't use it anyway)
  • Have MPIBugReporter be a value-level field of MPIChecker (that is, not a pointer). This ties the lifetime of its contained BugTypes to the checker, which fixes the ASan issue you were seeing and matches the behavior of other checkers.
  • Pass the clang::ento::BugReporter instance for the reporting context to MPIBugReporter's reporting methods rather storing it in MPIBugReporter (this should fix the ASan issue I was seeing).

I've updated with a proposed diff. What do you think?

Hi Devin,

this is much cleaner. Looks good for me!

This revision was automatically updated to reflect the committed changes.