Author: DonĂ¡t Nagy Date: 2025-09-08T13:16:24+02:00 New Revision: a80c393a9c498279a1ec9fd630535b9ff139b49f
URL: https://github.com/llvm/llvm-project/commit/a80c393a9c498279a1ec9fd630535b9ff139b49f DIFF: https://github.com/llvm/llvm-project/commit/a80c393a9c498279a1ec9fd630535b9ff139b49f.diff LOG: [analyzer] Consolidate the va_list checkers (#156682) Previously the analyzer had an undocumented top-level checker group called `valist` which offered several checkers to detect use of uninitialized `va_list` objects and leaks of `va_list`s. As the responsibilities of these checkers were messily intertwined and `va_list` is a rarely used language feature, this commit simplifies the situation by consolidating these checkers into a single checker which will be called `security.VAList`. Note that I'm choosing the capitalization `VAList` to be consistent with the example of the AST node type `VAArgExpr`. I updated many variable names to ensure that `ValistChecker.cpp` uses this spelling everywhere (in CamelCased names). I'm planning to rename `ValistChecker.cpp` to `VAListChecker.cpp` in a follow-up commit. This commit also adds documentation for this checker in checkers.rst. Among the test files I preserved the existing separation but I eliminated some duplicated cases now that there is no way to separately enable the old sub-checkers. For the background of this change see also the discourse thread https://discourse.llvm.org/t/clean-up-valist-checkers/85277/3 Added: Modified: clang/docs/analyzer/checkers.rst clang/include/clang/StaticAnalyzer/Checkers/Checkers.td clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp clang/test/Analysis/valist-as-lazycompound.c clang/test/Analysis/valist-uninitialized-no-undef.c clang/test/Analysis/valist-uninitialized.c clang/test/Analysis/valist-unterminated.c Removed: ################################################################################ diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst index 9350def672a6d..76bd80b82a4d6 100644 --- a/clang/docs/analyzer/checkers.rst +++ b/clang/docs/analyzer/checkers.rst @@ -1859,6 +1859,32 @@ this) and always check the return value of these calls. This check corresponds to SEI CERT Rule `POS36-C <https://wiki.sei.cmu.edu/confluence/display/c/POS36-C.+Observe+correct+revocation+order+while+relinquishing+privileges>`_. +.. _security-VAList: + +security.VAList (C, C++) +"""""""""""""""""""""""" +Reports use of uninitialized (or already released) ``va_list`` objects and +situations where a ``va_start`` call is not followed by ``va_end``. + +Report out of bounds access to memory that is before the start or after the end +of the accessed region (array, heap-allocated region, string literal etc.). +This usually means incorrect indexing, but the checker also detects access via +the operators ``*`` and ``->``. + +.. code-block:: c + + int test_use_after_release(int x, ...) { + va_list va; + va_start(va, x); + va_end(va); + return va_arg(va, int); // warn: va is uninitialized + } + + void test_leak(int x, ...) { + va_list va; + va_start(va, x); + } // warn: va is leaked + .. _unix-checkers: unix diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index c6c856bf7a773..a1f5bdfb9edf1 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -64,8 +64,6 @@ def Cplusplus : Package<"cplusplus">; def CplusplusAlpha : Package<"cplusplus">, ParentPackage<Alpha>; def CplusplusOptIn : Package<"cplusplus">, ParentPackage<OptIn>; -def Valist : Package<"valist">; - def DeadCode : Package<"deadcode">; def DeadCodeAlpha : Package<"deadcode">, ParentPackage<Alpha>; @@ -779,35 +777,6 @@ def SmartPtrChecker: Checker<"SmartPtr">, } // end: "alpha.cplusplus" - -//===----------------------------------------------------------------------===// -// Valist checkers. -//===----------------------------------------------------------------------===// - -let ParentPackage = Valist in { - -def ValistBase : Checker<"ValistBase">, - HelpText<"Gathers information about va_lists.">, - Documentation<NotDocumented>, - Hidden; - -def UninitializedChecker : Checker<"Uninitialized">, - HelpText<"Check for usages of uninitialized (or already released) va_lists.">, - Dependencies<[ValistBase]>, - Documentation<NotDocumented>; - -def UnterminatedChecker : Checker<"Unterminated">, - HelpText<"Check for va_lists which are not released by a va_end call.">, - Dependencies<[ValistBase]>, - Documentation<NotDocumented>; - -def CopyToSelfChecker : Checker<"CopyToSelf">, - HelpText<"Check for va_lists which are copied onto itself.">, - Dependencies<[ValistBase]>, - Documentation<NotDocumented>; - -} // end : "valist" - //===----------------------------------------------------------------------===// // Deadcode checkers. //===----------------------------------------------------------------------===// @@ -982,6 +951,10 @@ let ParentPackage = Security in { "'setuid(getuid())' (CERT: POS36-C)">, Documentation<HasDocumentation>; + def VAListChecker : Checker<"VAList">, + HelpText<"Warn on misuse of va_list objects">, + Documentation<HasDocumentation>; + } // end "security" let ParentPackage = ENV in { diff --git a/clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp index bd2f88c7b1bcc..2355abdaa060c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp @@ -27,28 +27,21 @@ REGISTER_SET_WITH_PROGRAMSTATE(InitializedVALists, const MemRegion *) namespace { typedef SmallVector<const MemRegion *, 2> RegionVector; -class ValistChecker : public Checker<check::PreCall, check::PreStmt<VAArgExpr>, +class VAListChecker : public Checker<check::PreCall, check::PreStmt<VAArgExpr>, check::DeadSymbols> { - mutable std::unique_ptr<BugType> BT_leakedvalist, BT_uninitaccess; + const BugType LeakBug{this, "Leaked va_list", categories::MemoryError, + /*SuppressOnSink=*/true}; + const BugType UninitAccessBug{this, "Uninitialized va_list", + categories::MemoryError}; struct VAListAccepter { CallDescription Func; - int VAListPos; + int ParamIndex; }; static const SmallVector<VAListAccepter, 15> VAListAccepters; static const CallDescription VaStart, VaEnd, VaCopy; public: - enum CheckKind { - CK_Uninitialized, - CK_Unterminated, - CK_CopyToSelf, - CK_NumCheckKinds - }; - - bool ChecksEnabled[CK_NumCheckKinds] = {false}; - CheckerNameRef CheckNames[CK_NumCheckKinds]; - void checkPreStmt(const VAArgExpr *VAA, CheckerContext &C) const; void checkPreCall(const CallEvent &Call, CheckerContext &C) const; void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const; @@ -61,17 +54,16 @@ class ValistChecker : public Checker<check::PreCall, check::PreStmt<VAArgExpr>, void reportUninitializedAccess(const MemRegion *VAList, StringRef Msg, CheckerContext &C) const; - void reportLeakedVALists(const RegionVector &LeakedVALists, StringRef Msg1, - StringRef Msg2, CheckerContext &C, ExplodedNode *N, - bool ReportUninit = false) const; + void reportLeaked(const RegionVector &Leaked, StringRef Msg1, StringRef Msg2, + CheckerContext &C, ExplodedNode *N) const; void checkVAListStartCall(const CallEvent &Call, CheckerContext &C, bool IsCopy) const; void checkVAListEndCall(const CallEvent &Call, CheckerContext &C) const; - class ValistBugVisitor : public BugReporterVisitor { + class VAListBugVisitor : public BugReporterVisitor { public: - ValistBugVisitor(const MemRegion *Reg, bool IsLeak = false) + VAListBugVisitor(const MemRegion *Reg, bool IsLeak = false) : Reg(Reg), IsLeak(IsLeak) {} void Profile(llvm::FoldingSetNodeID &ID) const override { static int X = 0; @@ -99,8 +91,8 @@ class ValistChecker : public Checker<check::PreCall, check::PreStmt<VAArgExpr>, }; }; -const SmallVector<ValistChecker::VAListAccepter, 15> - ValistChecker::VAListAccepters = {{{CDM::CLibrary, {"vfprintf"}, 3}, 2}, +const SmallVector<VAListChecker::VAListAccepter, 15> + VAListChecker::VAListAccepters = {{{CDM::CLibrary, {"vfprintf"}, 3}, 2}, {{CDM::CLibrary, {"vfscanf"}, 3}, 2}, {{CDM::CLibrary, {"vprintf"}, 2}, 1}, {{CDM::CLibrary, {"vscanf"}, 2}, 1}, @@ -116,14 +108,14 @@ const SmallVector<ValistChecker::VAListAccepter, 15> // vsnprintf, vsprintf has no wide version {{CDM::CLibrary, {"vswscanf"}, 3}, 2}}; -const CallDescription ValistChecker::VaStart(CDM::CLibrary, +const CallDescription VAListChecker::VaStart(CDM::CLibrary, {"__builtin_va_start"}, /*Args=*/2, /*Params=*/1), - ValistChecker::VaCopy(CDM::CLibrary, {"__builtin_va_copy"}, 2), - ValistChecker::VaEnd(CDM::CLibrary, {"__builtin_va_end"}, 1); + VAListChecker::VaCopy(CDM::CLibrary, {"__builtin_va_copy"}, 2), + VAListChecker::VaEnd(CDM::CLibrary, {"__builtin_va_end"}, 1); } // end anonymous namespace -void ValistChecker::checkPreCall(const CallEvent &Call, +void VAListChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const { if (VaStart.matches(Call)) checkVAListStartCall(Call, C, false); @@ -137,8 +129,8 @@ void ValistChecker::checkPreCall(const CallEvent &Call, continue; bool Symbolic; const MemRegion *VAList = - getVAListAsRegion(Call.getArgSVal(FuncInfo.VAListPos), - Call.getArgExpr(FuncInfo.VAListPos), Symbolic, C); + getVAListAsRegion(Call.getArgSVal(FuncInfo.ParamIndex), + Call.getArgExpr(FuncInfo.ParamIndex), Symbolic, C); if (!VAList) return; @@ -159,17 +151,17 @@ void ValistChecker::checkPreCall(const CallEvent &Call, } } -const MemRegion *ValistChecker::getVAListAsRegion(SVal SV, const Expr *E, +const MemRegion *VAListChecker::getVAListAsRegion(SVal SV, const Expr *E, bool &IsSymbolic, CheckerContext &C) const { const MemRegion *Reg = SV.getAsRegion(); if (!Reg) return nullptr; // TODO: In the future this should be abstracted away by the analyzer. - bool VaListModelledAsArray = false; + bool VAListModelledAsArray = false; if (const auto *Cast = dyn_cast<CastExpr>(E)) { QualType Ty = Cast->getType(); - VaListModelledAsArray = + VAListModelledAsArray = Ty->isPointerType() && Ty->getPointeeType()->isRecordType(); } if (const auto *DeclReg = Reg->getAs<DeclRegion>()) { @@ -179,17 +171,16 @@ const MemRegion *ValistChecker::getVAListAsRegion(SVal SV, const Expr *E, IsSymbolic = Reg && Reg->getBaseRegion()->getAs<SymbolicRegion>(); // Some VarRegion based VA lists reach here as ElementRegions. const auto *EReg = dyn_cast_or_null<ElementRegion>(Reg); - return (EReg && VaListModelledAsArray) ? EReg->getSuperRegion() : Reg; + return (EReg && VAListModelledAsArray) ? EReg->getSuperRegion() : Reg; } -void ValistChecker::checkPreStmt(const VAArgExpr *VAA, +void VAListChecker::checkPreStmt(const VAArgExpr *VAA, CheckerContext &C) const { ProgramStateRef State = C.getState(); - const Expr *VASubExpr = VAA->getSubExpr(); - SVal VAListSVal = C.getSVal(VASubExpr); + const Expr *ArgExpr = VAA->getSubExpr(); + SVal VAListSVal = C.getSVal(ArgExpr); bool Symbolic; - const MemRegion *VAList = - getVAListAsRegion(VAListSVal, VASubExpr, Symbolic, C); + const MemRegion *VAList = getVAListAsRegion(VAListSVal, ArgExpr, Symbolic, C); if (!VAList) return; if (Symbolic) @@ -199,20 +190,19 @@ void ValistChecker::checkPreStmt(const VAArgExpr *VAA, VAList, "va_arg() is called on an uninitialized va_list", C); } -void ValistChecker::checkDeadSymbols(SymbolReaper &SR, +void VAListChecker::checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const { ProgramStateRef State = C.getState(); - InitializedVAListsTy TrackedVALists = State->get<InitializedVALists>(); - RegionVector LeakedVALists; - for (auto Reg : TrackedVALists) { + InitializedVAListsTy Tracked = State->get<InitializedVALists>(); + RegionVector Leaked; + for (const MemRegion *Reg : Tracked) { if (SR.isLiveRegion(Reg)) continue; - LeakedVALists.push_back(Reg); + Leaked.push_back(Reg); State = State->remove<InitializedVALists>(Reg); } if (ExplodedNode *N = C.addTransition(State)) - reportLeakedVALists(LeakedVALists, "Initialized va_list", " is leaked", C, - N); + reportLeaked(Leaked, "Initialized va_list", " is leaked", C, N); } // This function traverses the exploded graph backwards and finds the node where @@ -220,7 +210,7 @@ void ValistChecker::checkDeadSymbols(SymbolReaper &SR, // It is not likely that there are several diff erent va_lists that belongs to // diff erent stack frames, so that case is not yet handled. const ExplodedNode * -ValistChecker::getStartCallSite(const ExplodedNode *N, +VAListChecker::getStartCallSite(const ExplodedNode *N, const MemRegion *Reg) const { const LocationContext *LeakContext = N->getLocationContext(); const ExplodedNode *StartCallNode = N; @@ -244,42 +234,21 @@ ValistChecker::getStartCallSite(const ExplodedNode *N, return StartCallNode; } -void ValistChecker::reportUninitializedAccess(const MemRegion *VAList, +void VAListChecker::reportUninitializedAccess(const MemRegion *VAList, StringRef Msg, CheckerContext &C) const { - if (!ChecksEnabled[CK_Uninitialized]) - return; if (ExplodedNode *N = C.generateErrorNode()) { - if (!BT_uninitaccess) - BT_uninitaccess.reset(new BugType(CheckNames[CK_Uninitialized], - "Uninitialized va_list", - categories::MemoryError)); - auto R = std::make_unique<PathSensitiveBugReport>(*BT_uninitaccess, Msg, N); + auto R = std::make_unique<PathSensitiveBugReport>(UninitAccessBug, Msg, N); R->markInteresting(VAList); - R->addVisitor(std::make_unique<ValistBugVisitor>(VAList)); + R->addVisitor(std::make_unique<VAListBugVisitor>(VAList)); C.emitReport(std::move(R)); } } -void ValistChecker::reportLeakedVALists(const RegionVector &LeakedVALists, - StringRef Msg1, StringRef Msg2, - CheckerContext &C, ExplodedNode *N, - bool ReportUninit) const { - if (!(ChecksEnabled[CK_Unterminated] || - (ChecksEnabled[CK_Uninitialized] && ReportUninit))) - return; - for (auto Reg : LeakedVALists) { - if (!BT_leakedvalist) { - // FIXME: maybe creating a new check name for this type of bug is a better - // solution. - BT_leakedvalist.reset(new BugType( - static_cast<StringRef>(CheckNames[CK_Unterminated]).empty() - ? CheckNames[CK_Uninitialized] - : CheckNames[CK_Unterminated], - "Leaked va_list", categories::MemoryError, - /*SuppressOnSink=*/true)); - } - +void VAListChecker::reportLeaked(const RegionVector &Leaked, StringRef Msg1, + StringRef Msg2, CheckerContext &C, + ExplodedNode *N) const { + for (const MemRegion *Reg : Leaked) { const ExplodedNode *StartNode = getStartCallSite(N, Reg); PathDiagnosticLocation LocUsedForUniqueing; @@ -296,15 +265,15 @@ void ValistChecker::reportLeakedVALists(const RegionVector &LeakedVALists, OS << Msg2; auto R = std::make_unique<PathSensitiveBugReport>( - *BT_leakedvalist, OS.str(), N, LocUsedForUniqueing, + LeakBug, OS.str(), N, LocUsedForUniqueing, StartNode->getLocationContext()->getDecl()); R->markInteresting(Reg); - R->addVisitor(std::make_unique<ValistBugVisitor>(Reg, true)); + R->addVisitor(std::make_unique<VAListBugVisitor>(Reg, true)); C.emitReport(std::move(R)); } } -void ValistChecker::checkVAListStartCall(const CallEvent &Call, +void VAListChecker::checkVAListStartCall(const CallEvent &Call, CheckerContext &C, bool IsCopy) const { bool Symbolic; const MemRegion *VAList = @@ -318,20 +287,19 @@ void ValistChecker::checkVAListStartCall(const CallEvent &Call, const MemRegion *Arg2 = getVAListAsRegion(Call.getArgSVal(1), Call.getArgExpr(1), Symbolic, C); if (Arg2) { - if (ChecksEnabled[CK_CopyToSelf] && VAList == Arg2) { - RegionVector LeakedVALists{VAList}; + if (VAList == Arg2) { + RegionVector Leaked{VAList}; if (ExplodedNode *N = C.addTransition(State)) - reportLeakedVALists(LeakedVALists, "va_list", - " is copied onto itself", C, N, true); + reportLeaked(Leaked, "va_list", " is copied onto itself", C, N); return; - } else if (!State->contains<InitializedVALists>(Arg2) && !Symbolic) { + } + if (!State->contains<InitializedVALists>(Arg2) && !Symbolic) { if (State->contains<InitializedVALists>(VAList)) { State = State->remove<InitializedVALists>(VAList); - RegionVector LeakedVALists{VAList}; + RegionVector Leaked{VAList}; if (ExplodedNode *N = C.addTransition(State)) - reportLeakedVALists(LeakedVALists, "Initialized va_list", - " is overwritten by an uninitialized one", C, N, - true); + reportLeaked(Leaked, "Initialized va_list", + " is overwritten by an uninitialized one", C, N); } else { reportUninitializedAccess(Arg2, "Uninitialized va_list is copied", C); } @@ -340,10 +308,10 @@ void ValistChecker::checkVAListStartCall(const CallEvent &Call, } } if (State->contains<InitializedVALists>(VAList)) { - RegionVector LeakedVALists{VAList}; + RegionVector Leaked{VAList}; if (ExplodedNode *N = C.addTransition(State)) - reportLeakedVALists(LeakedVALists, "Initialized va_list", - " is initialized again", C, N); + reportLeaked(Leaked, "Initialized va_list", " is initialized again", C, + N); return; } @@ -351,7 +319,7 @@ void ValistChecker::checkVAListStartCall(const CallEvent &Call, C.addTransition(State); } -void ValistChecker::checkVAListEndCall(const CallEvent &Call, +void VAListChecker::checkVAListEndCall(const CallEvent &Call, CheckerContext &C) const { bool Symbolic; const MemRegion *VAList = @@ -374,7 +342,7 @@ void ValistChecker::checkVAListEndCall(const CallEvent &Call, C.addTransition(State); } -PathDiagnosticPieceRef ValistChecker::ValistBugVisitor::VisitNode( +PathDiagnosticPieceRef VAListChecker::VAListBugVisitor::VisitNode( const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &) { ProgramStateRef State = N->getState(); ProgramStateRef StatePrev = N->getFirstPred()->getState(); @@ -399,26 +367,8 @@ PathDiagnosticPieceRef ValistChecker::ValistBugVisitor::VisitNode( return std::make_shared<PathDiagnosticEventPiece>(Pos, Msg, true); } -void ento::registerValistBase(CheckerManager &mgr) { - mgr.registerChecker<ValistChecker>(); -} - -bool ento::shouldRegisterValistBase(const CheckerManager &mgr) { - return true; +void ento::registerVAListChecker(CheckerManager &Mgr) { + Mgr.registerChecker<VAListChecker>(); } -#define REGISTER_CHECKER(name) \ - void ento::register##name##Checker(CheckerManager &mgr) { \ - ValistChecker *checker = mgr.getChecker<ValistChecker>(); \ - checker->ChecksEnabled[ValistChecker::CK_##name] = true; \ - checker->CheckNames[ValistChecker::CK_##name] = \ - mgr.getCurrentCheckerName(); \ - } \ - \ - bool ento::shouldRegister##name##Checker(const CheckerManager &mgr) { \ - return true; \ - } - -REGISTER_CHECKER(Uninitialized) -REGISTER_CHECKER(Unterminated) -REGISTER_CHECKER(CopyToSelf) +bool ento::shouldRegisterVAListChecker(const CheckerManager &) { return true; } diff --git a/clang/test/Analysis/valist-as-lazycompound.c b/clang/test/Analysis/valist-as-lazycompound.c index 3218e03a9c657..35a137321a67f 100644 --- a/clang/test/Analysis/valist-as-lazycompound.c +++ b/clang/test/Analysis/valist-as-lazycompound.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -triple gcc-linaro-arm-linux-gnueabihf -analyzer-checker=core,valist.Uninitialized,valist.CopyToSelf -analyzer-output=text -verify %s +// RUN: %clang_analyze_cc1 -triple gcc-linaro-arm-linux-gnueabihf -analyzer-checker=core,security.VAList -analyzer-output=text -verify %s // expected-no-diagnostics typedef unsigned int size_t; diff --git a/clang/test/Analysis/valist-uninitialized-no-undef.c b/clang/test/Analysis/valist-uninitialized-no-undef.c index 48631429be646..b8add29fc4803 100644 --- a/clang/test/Analysis/valist-uninitialized-no-undef.c +++ b/clang/test/Analysis/valist-uninitialized-no-undef.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=core,valist.Uninitialized,valist.CopyToSelf -analyzer-output=text -verify %s +// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=core,security.VAList -analyzer-output=text -verify %s #include "Inputs/system-header-simulator-for-valist.h" @@ -14,12 +14,6 @@ void call_inlined_uses_arg(int fst, ...) { inlined_uses_arg(va); // expected-note{{Calling 'inlined_uses_arg'}} } -void f6(va_list *fst, ...) { - va_start(*fst, fst); - (void)va_arg(*fst, int); - va_end(*fst); -} - int va_list_get_int(va_list *va) { return va_arg(*va, int); // no-warning } diff --git a/clang/test/Analysis/valist-uninitialized.c b/clang/test/Analysis/valist-uninitialized.c index 003592997eab8..689fc95c5a771 100644 --- a/clang/test/Analysis/valist-uninitialized.c +++ b/clang/test/Analysis/valist-uninitialized.c @@ -1,15 +1,15 @@ // RUN: %clang_analyze_cc1 -triple hexagon-unknown-linux -verify %s \ -// RUN: -analyzer-checker=core,valist.Uninitialized,valist.CopyToSelf \ +// RUN: -analyzer-checker=core,security.VAList \ // RUN: -analyzer-disable-checker=core.CallAndMessage \ // RUN: -analyzer-output=text // // RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -verify %s \ -// RUN: -analyzer-checker=core,valist.Uninitialized,valist.CopyToSelf \ +// RUN: -analyzer-checker=core,security.VAList \ // RUN: -analyzer-disable-checker=core.CallAndMessage \ // RUN: -analyzer-output=text // // RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu %s \ -// RUN: -analyzer-checker=core,valist.Uninitialized +// RUN: -analyzer-checker=core,security.VAList #include "Inputs/system-header-simulator-for-valist.h" @@ -47,12 +47,6 @@ void f4(int cond, ...) { // expected-note@-1{{va_end() is called on an uninitialized va_list}} } -void f5(va_list fst, ...) { - va_start(fst, fst); - (void)va_arg(fst, int); - va_end(fst); -} // no-warning - void f7(int *fst, ...) { va_list x; va_list *y = &x; @@ -70,14 +64,6 @@ void f8(int *fst, ...) { // expected-note@-1{{va_arg() is called on an uninitialized va_list}} } -// This only contains problems which are handled by varargs.Unterminated. -void reinit(int *fst, ...) { - va_list va; - va_start(va, fst); - va_start(va, fst); - (void)va_arg(va, int); -} // no-warning - void reinitOk(int *fst, ...) { va_list va; va_start(va, fst); @@ -100,27 +86,6 @@ void reinit3(int *fst, ...) { // expected-note@-1{{va_arg() is called on an uninitialized va_list}} } -void copyself(int fst, ...) { - va_list va; - va_start(va, fst); // expected-note{{Initialized va_list}} - va_copy(va, va); // expected-warning{{va_list 'va' is copied onto itself}} - // expected-note@-1{{va_list 'va' is copied onto itself}} - va_end(va); -} - -void copyselfUninit(int fst, ...) { - va_list va; - va_copy(va, va); // expected-warning{{va_list 'va' is copied onto itself}} - // expected-note@-1{{va_list 'va' is copied onto itself}} -} - -void copyOverwrite(int fst, ...) { - va_list va, va2; - va_start(va, fst); // expected-note{{Initialized va_list}} - va_copy(va, va2); // expected-warning{{Initialized va_list 'va' is overwritten by an uninitialized one}} - // expected-note@-1{{Initialized va_list 'va' is overwritten by an uninitialized one}} -} - void copyUnint(int fst, ...) { va_list va, va2; va_copy(va, va2); // expected-warning{{Uninitialized va_list is copied}} diff --git a/clang/test/Analysis/valist-unterminated.c b/clang/test/Analysis/valist-unterminated.c index 22d8fc710544e..cc892684b15fc 100644 --- a/clang/test/Analysis/valist-unterminated.c +++ b/clang/test/Analysis/valist-unterminated.c @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -triple hexagon-unknown-linux -analyzer-checker=core,valist.Unterminated,valist.CopyToSelf -analyzer-output=text -verify %s -// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=core,valist.Unterminated,valist.CopyToSelf -analyzer-output=text -verify %s +// RUN: %clang_analyze_cc1 -triple hexagon-unknown-linux -analyzer-checker=core,security.VAList -analyzer-output=text -verify %s +// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=core,security.VAList -analyzer-output=text -verify %s #include "Inputs/system-header-simulator-for-valist.h" @@ -97,12 +97,6 @@ void copyOverwrite(int fst, ...) { // expected-note@-1{{Initialized va_list 'va' is overwritten by an uninitialized one}} } -//This only generates a warning for the valist.Uninitialized checker -void copyUnint(int fst, ...) { - va_list va, va2; - va_copy(va, va2); -} // no-warning - void recopy(int fst, ...) { va_list va, va2; va_start(va, fst); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits