From ee5a21fda5efce750c21db5a1d635c9742f5859b Mon Sep 17 00:00:00 2001 From: Anna Zaks Date: Thu, 1 Dec 2011 16:41:58 +0000 Subject: [PATCH] [analyzer] Make KeychainAPI checker less aggressive. radar://10508828 We trigger an error if free is called after a possibly failed allocation. Do not trigger the error if we know that the buffer is not null. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145584 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Checkers/MacOSKeychainAPIChecker.cpp | 8 +++++--- test/Analysis/keychainAPI.m | 18 +++++++++++++++++- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp index b49684233a..78707e7e8a 100644 --- a/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp @@ -414,14 +414,16 @@ void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE, return; } - // If the return status is undefined or is error, report a bad call to free. - if (!definitelyDidnotReturnError(AS->Region, State, C.getSValBuilder())) { + // If the buffer can be null and the return status can be an error, + // report a bad call to free. + if (State->assume(cast(ArgSVal), false) && + !definitelyDidnotReturnError(AS->Region, State, C.getSValBuilder())) { ExplodedNode *N = C.addTransition(State); if (!N) return; initBugType(); BugReport *Report = new BugReport(*BT, - "Call to free data when error was returned during allocation.", N); + "Only call free if a valid (non-NULL) buffer was returned.", N); Report->addVisitor(new SecKeychainBugVisitor(ArgSM)); Report->addRange(ArgExpr->getSourceRange()); C.EmitReport(Report); diff --git a/test/Analysis/keychainAPI.m b/test/Analysis/keychainAPI.m index d10600dea5..613d74659f 100644 --- a/test/Analysis/keychainAPI.m +++ b/test/Analysis/keychainAPI.m @@ -77,7 +77,7 @@ void errRetVal() { void *outData; st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData); if (st == GenericError) // expected-warning{{Allocated data is not released: missing a call to 'SecKeychainItemFreeContent'.}} - SecKeychainItemFreeContent(ptr, outData); // expected-warning{{Call to free data when error was returned during allocation.}} + SecKeychainItemFreeContent(ptr, outData); // expected-warning{{Only call free if a valid (non-NULL) buffer was returned}} } // If null is passed in, the data is not allocated, so no need for the matching free. @@ -305,6 +305,22 @@ void DellocWithCFStringCreate4(CFAllocatorRef alloc) { } } +void radar10508828() { + UInt32 pwdLen = 0; + void* pwdBytes = 0; + OSStatus rc = SecKeychainFindGenericPassword(0, 3, "foo", 3, "bar", &pwdLen, &pwdBytes, 0); +#pragma unused(rc) + if (pwdBytes) + SecKeychainItemFreeContent(0, pwdBytes); +} + +void radar10508828_2() { + UInt32 pwdLen = 0; + void* pwdBytes = 0; + OSStatus rc = SecKeychainFindGenericPassword(0, 3, "foo", 3, "bar", &pwdLen, &pwdBytes, 0); + SecKeychainItemFreeContent(0, pwdBytes); // expected-warning {{Only call free if a valid (non-NULL) buffer was returned.}} +} + //Example from bug 10797. __inline__ static const char *__WBASLLevelString(int level) { -- 2.50.1