@@ -6021,6 +6021,60 @@ static bool checkAssignedAndUsed(const BoundsAttributedAssignmentGroup &Group,
60216021 return IsGroupSafe;
60226022}
60236023
6024+ // Checks if each assignment to count-attributed pointer in the group is safe.
6025+ static bool
6026+ checkAssignmentPatterns (const BoundsAttributedAssignmentGroup &Group,
6027+ UnsafeBufferUsageHandler &Handler, ASTContext &Ctx) {
6028+ // Collect dependent values.
6029+ DependentValuesTy DependentValues;
6030+ for (size_t I = 0 , N = Group.AssignedObjects .size (); I < N; ++I) {
6031+ const ValueDecl *VD = Group.AssignedObjects [I].Decl ;
6032+ const auto *Attr = VD->getAttr <DependerDeclsAttr>();
6033+ if (!Attr)
6034+ continue ;
6035+
6036+ const BinaryOperator *Assign = Group.Assignments [I];
6037+ const Expr *Value = Assign->getRHS ();
6038+
6039+ [[maybe_unused]] bool Inserted =
6040+ DependentValues.insert ({{VD, Attr->getIsDeref ()}, Value}).second ;
6041+ // Previous checks in `checkBoundsAttributedGroup` should have validated
6042+ // that we have only a single assignment.
6043+ assert (Inserted);
6044+ }
6045+
6046+ bool IsGroupSafe = true ;
6047+
6048+ // Check every pointer in the group.
6049+ for (size_t I = 0 , N = Group.AssignedObjects .size (); I < N; ++I) {
6050+ const ValueDecl *VD = Group.AssignedObjects [I].Decl ;
6051+
6052+ QualType Ty = VD->getType ();
6053+ const auto *CAT = Ty->getAs <CountAttributedType>();
6054+ if (!CAT && Ty->isPointerType ())
6055+ CAT = Ty->getPointeeType ()->getAs <CountAttributedType>();
6056+ if (!CAT)
6057+ continue ;
6058+
6059+ const BinaryOperator *Assign = Group.Assignments [I];
6060+
6061+ // TODO: Move this logic to isCountAttributedPointerArgumentSafeImpl.
6062+ const Expr *CountArg =
6063+ DependentValues.size () == 1 ? DependentValues.begin ()->second : nullptr ;
6064+
6065+ bool IsSafe = isCountAttributedPointerArgumentSafeImpl (
6066+ Ctx, Assign->getRHS (), CountArg, CAT, CAT->getCountExpr (),
6067+ CAT->isCountInBytes (), CAT->isOrNull (), &DependentValues);
6068+ if (!IsSafe) {
6069+ Handler.handleUnsafeCountAttributedPointerAssignment (
6070+ Assign, /* IsRelatedToDecl=*/ false , Ctx);
6071+ IsGroupSafe = false ;
6072+ }
6073+ }
6074+
6075+ return IsGroupSafe;
6076+ }
6077+
60246078// Checks if the bounds-attributed group is safe. This function returns false
60256079// iff the assignment group is unsafe and diagnostics have been emitted.
60266080static bool
@@ -6032,8 +6086,7 @@ checkBoundsAttributedGroup(const BoundsAttributedAssignmentGroup &Group,
60326086 return false ;
60336087 if (!checkAssignedAndUsed (Group, Handler, Ctx))
60346088 return false ;
6035- // TODO: Add more checks.
6036- return true ;
6089+ return checkAssignmentPatterns (Group, Handler, Ctx);
60376090}
60386091
60396092static void
0 commit comments