Author: guillem-bartrina-sonarsource Date: 2025-11-17T13:00:10+01:00 New Revision: fdbb888db53f156699ba3a94d5a0ce2005fd6e3c
URL: https://github.com/llvm/llvm-project/commit/fdbb888db53f156699ba3a94d5a0ce2005fd6e3c DIFF: https://github.com/llvm/llvm-project/commit/fdbb888db53f156699ba3a94d5a0ce2005fd6e3c.diff LOG: [analyzer] StdVariantChecker: fix crashes and incorrect retrieval of template arguments (#167341) Although very unusual, the SVal of the argument is not checked for UnknownVal, so we may get a null pointer dereference. In addition, the template arguments of the variant are retrieved incorrectly when type aliases are involved, causing crashes and FPs/FNs. Added: Modified: clang/lib/StaticAnalyzer/Checkers/StdVariantChecker.cpp clang/test/Analysis/std-variant-checker.cpp Removed: ################################################################################ diff --git a/clang/lib/StaticAnalyzer/Checkers/StdVariantChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdVariantChecker.cpp index db8bbee8761d5..c5dad610bef53 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StdVariantChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StdVariantChecker.cpp @@ -90,6 +90,9 @@ bool isStdVariant(const Type *Type) { static std::optional<ArrayRef<TemplateArgument>> getTemplateArgsFromVariant(const Type *VariantType) { const auto *TempSpecType = VariantType->getAs<TemplateSpecializationType>(); + while (TempSpecType && TempSpecType->isTypeAlias()) + TempSpecType = + TempSpecType->getAliasedType()->getAs<TemplateSpecializationType>(); if (!TempSpecType) return {}; @@ -219,10 +222,12 @@ class StdVariantChecker : public Checker<eval::Call, check::RegionChanges> { bool handleStdGetCall(const CallEvent &Call, CheckerContext &C) const { ProgramStateRef State = C.getState(); - const auto &ArgType = Call.getArgSVal(0) - .getType(C.getASTContext()) - ->getPointeeType() - .getTypePtr(); + SVal ArgSVal = Call.getArgSVal(0); + if (ArgSVal.isUnknown()) + return false; + + const auto &ArgType = + ArgSVal.getType(C.getASTContext())->getPointeeType().getTypePtr(); // We have to make sure that the argument is an std::variant. // There is another std::get with std::pair argument if (!isStdVariant(ArgType)) diff --git a/clang/test/Analysis/std-variant-checker.cpp b/clang/test/Analysis/std-variant-checker.cpp index 7f136c06b19cc..5b256b0f60dd0 100644 --- a/clang/test/Analysis/std-variant-checker.cpp +++ b/clang/test/Analysis/std-variant-checker.cpp @@ -355,4 +355,31 @@ void nonInlineFunctionCallPtr() { char c = std::get<char> (v); // no-warning (void)a; (void)c; -} \ No newline at end of file +} + +// ----------------------------------------------------------------------------// +// Misc +// ----------------------------------------------------------------------------// + +void unknownVal() { + // force the argument to be UnknownVal + (void)std::get<int>(*(std::variant<int, float>*)(int)3.14f); // no crash +} + +template <typename T> +using MyVariant = std::variant<int, float>; + +void typeAlias() { + MyVariant<bool> v; + + (void)std::get<int>(v); // no-warning +} + +template <template<typename> typename Container> +using MySpecialVariant = std::variant<int, float>; + +void complexTypeAlias() { + MySpecialVariant<std::vector> v; + + (void)std::get<int>(v); // no crash +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
