================
@@ -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

Reply via email to