================
@@ -447,16 +448,105 @@ static void printIdxWithOrdinalSuffix(llvm::raw_ostream 
&Os, unsigned Idx) {
   Os << Idx << llvm::getOrdinalSuffix(Idx);
 }
 
+static const FieldRegion *findUninitializedField(ProgramStateRef State,
+                                                 const TypedValueRegion *R) {
+  QualType Ty = R->getValueType();
+  SValBuilder &SVB = State->getStateManager().getSValBuilder();
+  ASTContext &Ctx = SVB.getContext();
+  MemRegionManager &MRMgr = SVB.getRegionManager();
+
+  if (R->getValueType()->isUnionType())
+    return nullptr;
+
+  if (Ty->isArrayType()) {
+    const auto *First = R;
+    const auto *Last = R;
+
+    while (const auto *AT = Ctx.getAsConstantArrayType(Ty)) {
+      if (AT->getSize().isZero())
+        return nullptr;
+
+      Ty = AT->getElementType();
+      First = MRMgr.getElementRegion(Ty, SVB.makeZeroArrayIndex(), First, Ctx);
+      Last = MRMgr.getElementRegion(
+          Ty, SVB.makeArrayIndex(AT->getSize().getZExtValue() - 1), Last, Ctx);
+    }
+
+    if (!Ty->isStructureType())
+      return nullptr;
+
+    if (const auto *FR = findUninitializedField(State, First))
+      return FR;
+
+    return First == Last ? nullptr : findUninitializedField(State, Last);
+  }
+
+  const auto *RT = Ty->getAsStructureType();
+  if (!RT)
+    return nullptr;
+  const auto *RD = RT->getDecl()->getDefinition();
+  if (!RD)
+    return nullptr;
+
+  for (const auto *FD : RD->fields()) {
+    if (!FD->getIdentifier())
+      continue;
+
+    const auto *FR = MRMgr.getFieldRegion(FD, R);
+    if (FD->getType()->isStructureType()) {
+      if (const auto *Uninit = findUninitializedField(State, FR))
+        return Uninit;
+    } else if (!FD->getType()->isAggregateType() &&
+               State->getSVal(FR).isUndef())
+      return FR;
+  }
+  return nullptr;
+}
+
 ProgramStateRef CStringChecker::checkInit(CheckerContext &C,
                                           ProgramStateRef State,
                                           AnyArgExpr Buffer, SVal Element,
-                                          SVal Size) const {
+                                          SVal Size, CharKind CK) const {
 
   // If a previous check has failed, propagate the failure.
   if (!State)
     return nullptr;
 
   SVal BufVal = C.getSVal(Buffer.Expression);
+  SValBuilder &SVB = C.getSValBuilder();
+  ASTContext &Ctx = SVB.getContext();
+
+  // Field initialization is meaningful only when the entire source object is
+  // read. Do not widen partial copies or nonzero offsets to their base object
+  if (UninitializedRead.isEnabled()) {
+    const auto *BufR = BufVal.getAsRegion();
+    const auto *Object = llvm::dyn_cast_or_null<TypedValueRegion>(
+        BufR ? BufR->StripCasts(false) : nullptr);
+
+    if (Object && !isa<ElementRegion>(Object)) {
----------------
bozicrHT wrote:

Yes, that is correct. The previous version filtered out copies of individual 
struct array elements. I updated the implementation to check the raw 
`TypedValueRegion` first and only fall back to `StripCasts(false)` when its 
type and size do not match the complete copied object.

This now handles both `&s1[0]` and `&s1[1]`.

https://github.com/llvm/llvm-project/pull/232824
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to