================
@@ -268,9 +219,115 @@ class FindUninitializedField {
return false;
}
+
+ void printFieldChain(llvm::raw_ostream &OS) {
+ if (FieldChain.size() == 1)
+ OS << " (e.g., field: '" << *FieldChain[0] << "')";
+ else {
+ OS << " (e.g., via the field chain: '";
+ bool First = true;
+ for (SmallVectorImpl<const FieldDecl *>::iterator DI =
FieldChain.begin(),
+ DE = FieldChain.end();
+ DI != DE; ++DI) {
+ if (First)
+ First = false;
+ else
+ OS << '.';
+ OS << **DI;
+ }
+ OS << "')";
+ }
+ }
};
} // namespace
+bool CallAndMessageChecker::uninitRefOrPointer(
+ CheckerContext &C, SVal V, SourceRange ArgRange, const Expr *ArgEx,
+ const BugType &BT, const ParmVarDecl *ParamDecl, int ArgumentNumber) const
{
+
+ if (!ChecksEnabled[CK_ArgPointeeInitializedness])
+ return false;
+
+ // No parameter declaration available, i.e. variadic function argument.
+ if (!ParamDecl)
+ return false;
+
+ QualType ParamT = ParamDecl->getType();
+ if (!ParamT->isPointerOrReferenceType())
+ return false;
+
+ QualType PointeeT = ParamT->getPointeeType();
+ if (!PointeeT.isConstQualified())
+ return false;
+
+ const MemRegion *SValMemRegion = V.getAsRegion();
+ if (!SValMemRegion)
+ return false;
+
+ // If parameter is declared as pointer to const in function declaration,
+ // then check if corresponding argument in function call is
+ // pointing to undefined symbol value (uninitialized memory).
+
+ const ProgramStateRef State = C.getState();
+ if (PointeeT->isVoidType())
+ PointeeT = C.getASTContext().CharTy;
+ const SVal PointeeV =
+ State->getSVal(SValMemRegion, PointeeT);
+
+ if (PointeeV.isUndef()) {
+ if (ExplodedNode *N = C.generateErrorNode()) {
+ SmallString<200> Buf;
+ llvm::raw_svector_ostream Os(Buf);
+ Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
+ << " function call argument is ";
+ if (ParamT->isPointerType())
+ Os << "a pointer to uninitialized value";
+ else
+ Os << "an uninitialized value";
+ auto R = std::make_unique<PathSensitiveBugReport>(BT, Os.str(), N);
+ R->addRange(ArgRange);
+ if (ArgEx)
+ bugreporter::trackExpressionValue(N, ArgEx, *R);
+
+ C.emitReport(std::move(R));
+ }
+ return true;
+ }
+
+ if (auto LV = PointeeV.getAs<nonloc::LazyCompoundVal>()) {
+ const LazyCompoundValData *D = LV->getCVData();
+ FindUninitializedField F(C.getState()->getStateManager().getStoreManager(),
+ C.getSValBuilder().getRegionManager(),
+ D->getStore());
+
+ if (F.Find(D->getRegion())) {
+ if (ExplodedNode *N = C.generateErrorNode()) {
+ SmallString<512> Buf;
+ llvm::raw_svector_ostream Os(Buf);
+ Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber +
1)
+ << " function call argument";
+ if (ParamT->isPointerType())
+ Os << " points to";
+ else
+ Os << " references";
+ Os << " an uninitialized value";
+
+ F.printFieldChain(Os);
+
+ auto R = std::make_unique<PathSensitiveBugReport>(BT, Os.str(), N);
----------------
NagyDonat wrote:
As above, I would suggest replacing this logic with a `llvm::formatv` call.
To do so I would replace the method `void printFieldChain(llvm::raw_ostream
&OS)` – which is a bit awkward to call – with a `std::string
describeFieldChain()` which perhaps still uses an internal stream as an
implementation detail, but provides a "cleaner" interface that simply returns a
string.
https://github.com/llvm/llvm-project/pull/164600
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits