Index: include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h =================================================================== --- include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -79,6 +79,7 @@ mutable IdentifierInfo *II = nullptr; mutable bool IsLookupDone = false; + // Represent the function name or method name, like "X" or "a::b::X". StringRef FuncName; unsigned RequiredArgs; @@ -96,7 +97,11 @@ : FuncName(FuncName), RequiredArgs(RequiredArgs) {} /// Get the name of the function that this object matches. - StringRef getFunctionName() const { return FuncName; } + StringRef getFunctionName() const { + auto QualifierNamePair = FuncName.rsplit("::"); + return QualifierNamePair.second.empty() ? QualifierNamePair.first + : QualifierNamePair.second; + } }; template Index: lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp +++ lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp @@ -13,13 +13,14 @@ // //===----------------------------------------------------------------------===// +#include "AllocationState.h" #include "ClangSACheckers.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" -#include "AllocationState.h" +#include "llvm/ADT/SmallVector.h" using namespace clang; using namespace ento; @@ -28,11 +29,12 @@ class DanglingInternalBufferChecker : public Checker { - CallDescription CStrFn; + const llvm::SmallVector CStrFnFamily = { + {"std::basic_string::c_str"}, {"std::basic_string::c_str"}, + {"std::basic_string::c_str"}, + {"std::basic_string::c_str"}}; public: - DanglingInternalBufferChecker() : CStrFn("c_str") {} - /// Record the connection between the symbol returned by c_str() and the /// corresponding string object region in the ProgramState. Mark the symbol /// released if the string object is destroyed. @@ -65,7 +67,15 @@ ProgramStateRef State = C.getState(); - if (Call.isCalled(CStrFn)) { + auto isCStrFnFamilyCall = [&](const CallEvent &Call) -> bool { + for (auto CStrFn : CStrFnFamily) { + if (Call.isCalled(CStrFn)) + return true; + } + return false; + }; + + if (isCStrFnFamilyCall(Call)) { SVal RawPtr = Call.getReturnValue(); if (!RawPtr.isUnknown()) { State = State->set(TypedR, RawPtr.getAsSymbol()); Index: lib/StaticAnalyzer/Core/CallEvent.cpp =================================================================== --- lib/StaticAnalyzer/Core/CallEvent.cpp +++ lib/StaticAnalyzer/Core/CallEvent.cpp @@ -28,6 +28,7 @@ #include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" #include "clang/Analysis/ProgramPoint.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/CrossTU/CrossTranslationUnit.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" @@ -65,6 +66,7 @@ using namespace clang; using namespace ento; +using namespace clang::ast_matchers; QualType CallEvent::getResultType() const { ASTContext &Ctx = getState()->getStateManager().getContext(); @@ -256,11 +258,24 @@ return false; if (!CD.IsLookupDone) { CD.IsLookupDone = true; - CD.II = &getState()->getStateManager().getContext().Idents.get(CD.FuncName); + CD.II = &getState()->getStateManager().getContext().Idents.get( + CD.getFunctionName()); } const IdentifierInfo *II = getCalleeIdentifier(); if (!II || II != CD.II) return false; + + const NamedDecl *ND = dyn_cast_or_null(getDecl()); + if (!ND) + return false; + + auto Matches = + match(namedDecl(hasName(CD.FuncName)).bind("match_qualified_name"), *ND, + LCtx->getAnalysisDeclContext()->getASTContext()); + + if (Matches.empty()) + return false; + return (CD.RequiredArgs == CallDescription::NoArgRequirement || CD.RequiredArgs == getNumArgs()); }