<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>