[PATCH] [analyzer] Detect use-after-free scenarios in -dealloc after calling [super dealloc]

David Kilzer ddkilzer at kilzer.net
Sat Aug 23 23:17:41 PDT 2014


> * Crash in ASTMatchers running `test/Analysis/PR2978.m` test, possibly due to invalid code in `-dealloc` method. Haven't figured out how to make a stand-alone test case yet.

Something is going horribly wrong dereferencing a `clang::Stmt *` into a `const clang::Stmt &` in this call:

  Finder.match(*S, Ctx);

Changing the pointer type to `const clang::Stmt *` as passed into the method had no effect.  I also tried this to no avail:

  const Stmt &SRef = *S;
  Finder.match(SRef, Ctx);

Here's an lldb session showing the badness.  I know something is going wrong because the value of `Node.Aligner` in the `match()` method is the same value as the `S` pointer (`0x000000010a033ce0`) prior to the call:


```
(lldb) run
Process 6895 launched: '/Volumes/Data/clang.git/llvm/Debug+Asserts/bin/clang' (x86_64)
Process 6895 stopped
* thread #1: tid = 0x39e920, 0x00000001010a5250 clang`scan_dealloc_for_self_after_super_dealloc(S=0x000000010a033ce0, Callback=0x00007fff5fbfc410, Ctx=0x000000010a822000) + 624 at CheckObjCDealloc.cpp:70, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x00000001010a5250 clang`scan_dealloc_for_self_after_super_dealloc(S=0x000000010a033ce0, Callback=0x00007fff5fbfc410, Ctx=0x000000010a822000) + 624 at CheckObjCDealloc.cpp:70
   67  	      stmt(hasDescendant(declRefExpr(to(varDecl(hasName("self"))))
   68  	                             .bind("self"))).bind("stmt");
   69  	  Finder.addMatcher(Matcher, &Callback);
-> 70  	  Finder.match(*S, Ctx);
   71  	  if (Callback.FoundMatch())
   72  	    return true;
   73  	
(lldb) p *S
(clang::Stmt) $4 = {
   = {
    Aligner = 0x000000000000008d
    StmtBits = (sClass = 141)
    CompoundStmtBits = (NumStmts = 0)
    ExprBits = {
      ValueKind = 0
      ObjectKind = 0
      TypeDependent = 0
      ValueDependent = 0
      InstantiationDependent = 0
      ContainsUnexpandedParameterPack = 0
    }
    CharacterLiteralBits = (Kind = 0)
    FloatingLiteralBits = (Semantics = 0, IsExact = 0)
    UnaryExprOrTypeTraitExprBits = (Kind = 0, IsType = 0)
    DeclRefExprBits = {
      HasQualifier = 0
      HasTemplateKWAndArgsInfo = 0
      HasFoundDecl = 0
      HadMultipleCandidates = 0
      RefersToEnclosingLocal = 0
    }
    CastExprBits = (Kind = 0, BasePathSize = 0)
    CallExprBits = (NumPreArgs = 0)
    ExprWithCleanupsBits = (NumObjects = 0)
    PseudoObjectExprBits = (NumSubExprs = 0, ResultIndex = 0)
    ObjCIndirectCopyRestoreExprBits = (ShouldCopy = 0)
    InitListExprBits = (HadArrayRangeDesignator = 0)
    TypeTraitExprBits = (Kind = 0, Value = 0, NumArgs = 0)
  }
}
(lldb) p S->getStmtClassName()
(const char *) $5 = 0x00000001044ea946 "ReturnStmt"
(lldb) p (*S).getStmtClassName()
(const char *) $6 = 0x00000001044ea946 "ReturnStmt"
(lldb) s
Process 6895 stopped
* thread #1: tid = 0x39e920, 0x00000001010b0b7a clang`void clang::ast_matchers::MatchFinder::match<clang::Stmt>(this=0x00007fff5fbfbe38, Node=0x000000010a033ce0, Context=0x000000010a822000) + 42 at ASTMatchFinder.h:160, queue = 'com.apple.main-thread', stop reason = step in
    frame #0: 0x00000001010b0b7a clang`void clang::ast_matchers::MatchFinder::match<clang::Stmt>(this=0x00007fff5fbfbe38, Node=0x000000010a033ce0, Context=0x000000010a822000) + 42 at ASTMatchFinder.h:160
   157 	  ///
   158 	  /// @{
   159 	  template <typename T> void match(const T &Node, ASTContext &Context) {
-> 160 	    match(clang::ast_type_traits::DynTypedNode::create(Node), Context);
   161 	  }
   162 	  void match(const clang::ast_type_traits::DynTypedNode &Node,
   163 	             ASTContext &Context);
(lldb) p Node.getStmtClassName()
(const char *) $7 = 0x0000002000000000
(lldb) p Node
(const clang::Stmt) $8 = {
   = {
    Aligner = 0x000000010a033ce0
    StmtBits = (sClass = 224)
    CompoundStmtBits = (NumStmts = 656188)
    ExprBits = {
      ValueKind = 0
      ObjectKind = 3
      TypeDependent = 1
      ValueDependent = 1
      InstantiationDependent = 0
      ContainsUnexpandedParameterPack = 0
    }
    CharacterLiteralBits = (Kind = 3)
    FloatingLiteralBits = (Semantics = 3, IsExact = 0)
    UnaryExprOrTypeTraitExprBits = (Kind = 3, IsType = 0)
    DeclRefExprBits = {
      HasQualifier = 1
      HasTemplateKWAndArgsInfo = 1
      HasFoundDecl = 0
      HadMultipleCandidates = 0
      RefersToEnclosingLocal = 0
    }
    CastExprBits = (Kind = 3, BasePathSize = 40)
    CallExprBits = (NumPreArgs = 1)
    ExprWithCleanupsBits = (NumObjects = 2563)
    PseudoObjectExprBits = (NumSubExprs = 3, ResultIndex = 10)
    ObjCIndirectCopyRestoreExprBits = (ShouldCopy = 1)
    InitListExprBits = (HadArrayRangeDesignator = 1)
    TypeTraitExprBits = (Kind = 3, Value = 0, NumArgs = 5)
  }
}
(lldb) 
```

One thing I can't tell is if `make` is compiling with the trunk clang I'm building, or whether it's using the clang I have installed with Xcode.

http://reviews.llvm.org/D5042






More information about the cfe-commits mailing list