[clang] [analyzer]:fix valistChecker false negative in windows platform (PR #72951)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Nov 29 00:20:47 PST 2023
https://github.com/mzyKi updated https://github.com/llvm/llvm-project/pull/72951
>From e62698df942c547f287f0e0fd5863d746d597f53 Mon Sep 17 00:00:00 2001
From: miaozhiyuan <miaozhiyuan at feysh.com>
Date: Tue, 21 Nov 2023 12:07:35 +0800
Subject: [PATCH] [analyzer]:fix valistChecker false negative in windows
platform
---
.../StaticAnalyzer/Checkers/ValistChecker.cpp | 51 +++++++++++++++----
1 file changed, 42 insertions(+), 9 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp
index 2d1b873abf73f09..0ab018af1ed549b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp
@@ -25,10 +25,13 @@ using namespace ento;
REGISTER_SET_WITH_PROGRAMSTATE(InitializedVALists, const MemRegion *)
namespace {
+const StringRef Valist = "va_list";
+
typedef SmallVector<const MemRegion *, 2> RegionVector;
-class ValistChecker : public Checker<check::PreCall, check::PreStmt<VAArgExpr>,
- check::DeadSymbols> {
+class ValistChecker
+ : public Checker<eval::Call, check::PreStmt<VAArgExpr>,
+ check::PreStmt<DeclStmt>, check::DeadSymbols> {
mutable std::unique_ptr<BugType> BT_leakedvalist, BT_uninitaccess;
struct VAListAccepter {
@@ -49,11 +52,13 @@ class ValistChecker : public Checker<check::PreCall, check::PreStmt<VAArgExpr>,
bool ChecksEnabled[CK_NumCheckKinds] = {false};
CheckerNameRef CheckNames[CK_NumCheckKinds];
+ void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const;
void checkPreStmt(const VAArgExpr *VAA, CheckerContext &C) const;
- void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
+ bool evalCall(const CallEvent &Call, CheckerContext &C) const;
void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
private:
+ bool isWinValistType(const VarDecl *VD) const;
const MemRegion *getVAListAsRegion(SVal SV, const Expr *VAExpr,
bool &IsSymbolic, CheckerContext &C) const;
const ExplodedNode *getStartCallSite(const ExplodedNode *N,
@@ -122,10 +127,9 @@ const CallDescription ValistChecker::VaStart({"__builtin_va_start"}, /*Args=*/2,
ValistChecker::VaEnd({"__builtin_va_end"}, 1);
} // end anonymous namespace
-void ValistChecker::checkPreCall(const CallEvent &Call,
- CheckerContext &C) const {
+bool ValistChecker::evalCall(const CallEvent &Call, CheckerContext &C) const {
if (!Call.isGlobalCFunction())
- return;
+ return false;
if (VaStart.matches(Call))
checkVAListStartCall(Call, C, false);
else if (VaCopy.matches(Call))
@@ -141,15 +145,15 @@ void ValistChecker::checkPreCall(const CallEvent &Call,
getVAListAsRegion(Call.getArgSVal(FuncInfo.VAListPos),
Call.getArgExpr(FuncInfo.VAListPos), Symbolic, C);
if (!VAList)
- return;
+ return false;
if (C.getState()->contains<InitializedVALists>(VAList))
- return;
+ return false;
// We did not see va_start call, but the source of the region is unknown.
// Be conservative and assume the best.
if (Symbolic)
- return;
+ return false;
SmallString<80> Errmsg("Function '");
Errmsg += FuncInfo.Func.getFunctionName();
@@ -158,6 +162,35 @@ void ValistChecker::checkPreCall(const CallEvent &Call,
break;
}
}
+ return C.isDifferent();
+}
+
+bool ValistChecker::isWinValistType(const VarDecl *VD) const {
+ ASTContext &Ctx = VD->getASTContext();
+ QualType T = VD->getType();
+ if (T.isNull()) {
+ return false;
+ }
+ if (!Valist.equals(T.getAsString())) {
+ return false;
+ }
+ return T.getDesugaredType(Ctx)->isPointerType() &&
+ T.getDesugaredType(Ctx)->getPointeeType()->isCharType();
+}
+
+void ValistChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
+ for (const auto *I : DS->decls()) {
+ const auto *VD = dyn_cast<VarDecl>(I);
+ if (nullptr == VD || !isWinValistType(VD)) {
+ continue;
+ }
+ ProgramStateRef State = C.getState();
+ const VarRegion *VR = State->getRegion(VD, C.getLocationContext());
+ SValBuilder &SVB = C.getSValBuilder();
+ State = State->bindLoc(State->getLValue(VD, C.getLocationContext()),
+ SVB.makeLoc(VR), C.getLocationContext());
+ C.addTransition(State);
+ }
}
const MemRegion *ValistChecker::getVAListAsRegion(SVal SV, const Expr *E,
More information about the cfe-commits
mailing list