<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div>Just for paranoia's sake, can you also include a test case where there are two use-after-free arguments in the same function call? It's okay if we only warn about one of them (current behavior), but just so that we don't get a crash or something.</div><div><br></div><div>Jordan</div><div><br></div><br><div><div>On Apr 10, 2013, at 15:21 , Anton Yartsev <<a href="mailto:anton.yartsev@gmail.com">anton.yartsev@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Author: ayartsev<br>Date: Wed Apr 10 17:21:41 2013<br>New Revision: 179230<br><br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project?rev=179230&view=rev">http://llvm.org/viewvc/llvm-project?rev=179230&view=rev</a><br>Log:<br>[analyzer] Switched to checkPreCall interface for detecting usage after free.<br><br>Now the check is also applied to arguments for Objective-C method calls and to 'this' pointer.<br><br>Modified:<br>   cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp<br>   cfe/trunk/test/Analysis/NewDelete-checker-test.cpp<br>   cfe/trunk/test/Analysis/malloc.mm<br>   cfe/trunk/test/Analysis/new.cpp<br><br>Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=179230&r1=179229&r2=179230&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=179230&r1=179229&r2=179230&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original)<br>+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Wed Apr 10 17:21:41 2013<br>@@ -147,7 +147,7 @@ class MallocChecker : public Checker<che<br>                                     check::PointerEscape,<br>                                     check::ConstPointerEscape,<br>                                     check::PreStmt<ReturnStmt>,<br>-                                     check::PreStmt<CallExpr>,<br>+                                     check::PreCall,<br>                                     check::PostStmt<CallExpr>,<br>                                     check::PostStmt<CXXNewExpr>,<br>                                     check::PreStmt<CXXDeleteExpr>,<br>@@ -181,7 +181,7 @@ public:<br><br>  ChecksFilter Filter;<br><br>-  void checkPreStmt(const CallExpr *S, CheckerContext &C) const;<br>+  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;<br>  void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;<br>  void checkPostStmt(const CXXNewExpr *NE, CheckerContext &C) const;<br>  void checkPreStmt(const CXXDeleteExpr *DE, CheckerContext &C) const;<br>@@ -1671,26 +1671,39 @@ void MallocChecker::checkDeadSymbols(Sym<br>  C.addTransition(state->set<RegionState>(RS), N);<br>}<br><br>-void MallocChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {<br>+void MallocChecker::checkPreCall(const CallEvent &Call,<br>+                                 CheckerContext &C) const {<br>+<br>  // We will check for double free in the post visit.<br>-  if ((Filter.CMallocOptimistic || Filter.CMallocPessimistic) &&<br>-      isFreeFunction(C.getCalleeDecl(CE), C.getASTContext()))<br>-    return;<br>+  if (const AnyFunctionCall *FC = dyn_cast<AnyFunctionCall>(&Call)) {<br>+    const FunctionDecl *FD = FC->getDecl();<br>+    if (!FD)<br>+      return;<br><br>-  if (Filter.CNewDeleteChecker &&<br>-      isStandardNewDelete(C.getCalleeDecl(CE), C.getASTContext()))<br>-    return;<br>+    if ((Filter.CMallocOptimistic || Filter.CMallocPessimistic) &&<br>+        isFreeFunction(FD, C.getASTContext()))<br>+      return;<br><br>-  // Check use after free, when a freed pointer is passed to a call.<br>-  ProgramStateRef State = C.getState();<br>-  for (CallExpr::const_arg_iterator I = CE->arg_begin(),<br>-                                    E = CE->arg_end(); I != E; ++I) {<br>-    const Expr *A = *I;<br>-    if (A->getType().getTypePtr()->isAnyPointerType()) {<br>-      SymbolRef Sym = C.getSVal(A).getAsSymbol();<br>+    if (Filter.CNewDeleteChecker &&<br>+        isStandardNewDelete(FD, C.getASTContext()))<br>+      return;<br>+  }<br>+<br>+  // Check if the callee of a method is deleted.<br>+  if (const CXXInstanceCall *CC = dyn_cast<CXXInstanceCall>(&Call)) {<br>+    SymbolRef Sym = CC->getCXXThisVal().getAsSymbol();<br>+    if (!Sym || checkUseAfterFree(Sym, C, CC->getCXXThisExpr()))<br>+      return;<br>+  }<br>+<br>+  // Check arguments for being used after free.<br>+  for (unsigned I = 0, E = Call.getNumArgs(); I != E; ++I) {<br>+    SVal ArgSVal = Call.getArgSVal(I);<br>+    if (ArgSVal.getAs<Loc>()) {<br>+      SymbolRef Sym = ArgSVal.getAsSymbol();<br>      if (!Sym)<br>        continue;<br>-      if (checkUseAfterFree(Sym, C, A))<br>+      if (checkUseAfterFree(Sym, C, Call.getArgExpr(I)))<br>        return;<br>    }<br>  }<br><br>Modified: cfe/trunk/test/Analysis/NewDelete-checker-test.cpp<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/NewDelete-checker-test.cpp?rev=179230&r1=179229&r2=179230&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/NewDelete-checker-test.cpp?rev=179230&r1=179229&r2=179230&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/Analysis/NewDelete-checker-test.cpp (original)<br>+++ cfe/trunk/test/Analysis/NewDelete-checker-test.cpp Wed Apr 10 17:21:41 2013<br>@@ -54,7 +54,6 @@ void testGlobalNoThrowPlacementExprNewBe<br>// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}<br>#endif<br><br>-<br>//----- Standard pointer placement operators<br>void testGlobalPointerPlacementNew() {<br>  int i;<br>@@ -91,14 +90,54 @@ void testNewInvalidationPlacement(PtrWra<br>// other checks<br>//---------------<br><br>-void f(int *);<br>+class SomeClass {<br>+public:<br>+  void f(int *p);<br>+};<br>+<br>+void f(int *p1, int *p2 = 0, int *p3 = 0);<br>+void g(SomeClass &c, ...);<br><br>-void testUseAfterDelete() {<br>+void testUseFirstArgAfterDelete() {<br>  int *p = new int;<br>  delete p;<br>  f(p); // expected-warning{{Use of memory after it is freed}}<br>}<br><br>+void testUseMiddleArgAfterDelete(int *p) {<br>+  delete p;<br>+  f(0, p); // expected-warning{{Use of memory after it is freed}}<br>+}<br>+<br>+void testUseLastArgAfterDelete(int *p) {<br>+  delete p;<br>+  f(0, 0, p); // expected-warning{{Use of memory after it is freed}}<br>+}<br>+<br>+void testUseRefArgAfterDelete(SomeClass &c) {<br>+  delete &c;<br>+  g(c); // expected-warning{{Use of memory after it is freed}}<br>+}<br>+<br>+void testVariadicArgAfterDelete() {<br>+  SomeClass c;<br>+  int *p = new int;<br>+  delete p;<br>+  g(c, 0, p); // expected-warning{{Use of memory after it is freed}}<br>+}<br>+<br>+void testUseMethodArgAfterDelete(int *p) {<br>+  SomeClass *c = new SomeClass;<br>+  delete p;<br>+  c->f(p); // expected-warning{{Use of memory after it is freed}}<br>+}<br>+<br>+void testUseThisAfterDelete() {<br>+  SomeClass *c = new SomeClass;<br>+  delete c;<br>+  c->f(0); // expected-warning{{Use of memory after it is freed}}<br>+}<br>+<br>void testDeleteAlloca() {<br>  int *p = (int *)__builtin_alloca(sizeof(int));<br>  delete p; // expected-warning{{Memory allocated by alloca() should not be deallocated}}<br><br>Modified: cfe/trunk/test/Analysis/malloc.mm<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.mm?rev=179230&r1=179229&r2=179230&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.mm?rev=179230&r1=179229&r2=179230&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/Analysis/malloc.mm (original)<br>+++ cfe/trunk/test/Analysis/malloc.mm Wed Apr 10 17:21:41 2013<br>@@ -81,7 +81,17 @@ void testRelinquished2() {<br>  void *data = malloc(42);<br>  NSData *nsdata;<br>  free(data);<br>-  [NSData dataWithBytesNoCopy:data length:42]; // expected-warning {{Attempt to free released memory}}<br>+  [NSData dataWithBytesNoCopy:data length:42]; // expected-warning {{Use of memory after it is freed}}<br>+}<br>+<br>+@interface My<br>++ (void)param:(void *)p;<br>+@end<br>+<br>+void testUseAfterFree() {<br>+  int *p = (int *)malloc(sizeof(int));<br>+  free(p);<br>+  [My param:p];  // expected-warning{{Use of memory after it is freed}}<br>}<br><br>void testNoCopy() {<br><br>Modified: cfe/trunk/test/Analysis/new.cpp<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/new.cpp?rev=179230&r1=179229&r2=179230&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/new.cpp?rev=179230&r1=179229&r2=179230&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/Analysis/new.cpp (original)<br>+++ cfe/trunk/test/Analysis/new.cpp Wed Apr 10 17:21:41 2013<br>@@ -8,6 +8,12 @@ extern "C" void *malloc(size_t);<br>extern "C" void free(void *);<br><br>int someGlobal;<br>+<br>+class SomeClass {<br>+public:<br>+  void f(int *p);<br>+};<br>+<br>void testImplicitlyDeclaredGlobalNew() {<br>  if (someGlobal != 0)<br>    return;<br>@@ -101,6 +107,12 @@ void testCacheOut(PtrWrapper w) {<br>  new (&w.x) (int*)(0); // we cache out here; don't crash<br>}<br><br>+void testUseAfter(int *p) {<br>+  SomeClass *c = new SomeClass;<br>+  free(p);<br>+  c->f(p); // expected-warning{{Use of memory after it is freed}}<br>+  delete c;<br>+}<br><br>//--------------------------------------------------------------------<br>// Check for intersection with other checkers from MallocChecker.cpp<span class="Apple-converted-space"> </span><br>@@ -152,6 +164,12 @@ void testCustomPlacementNewAfterFree() {<br>  p = new(0, p) int; // expected-warning{{Use of memory after it is freed}}<br>}<br><br>+void testUsingThisAfterDelete() {<br>+  SomeClass *c = new SomeClass;<br>+  delete c;<br>+  c->f(0); // no-warning<br>+}<br>+<br>//--------------------------------<br>// Incorrectly-modelled behavior<br>//--------------------------------<br><br><br>_______________________________________________<br>cfe-commits mailing list<br><a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br><a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br></div></blockquote></div><br></body></html>