Skip to content

Commit 4239eee

Browse files
[WIP][-Wunsafe-buffer-usage] Check __counted_by() assignments
Check assignments to count-attributed pointer and dependent variables. rdar://128160398 rdar://128161580
1 parent df1f135 commit 4239eee

File tree

9 files changed

+1169
-27
lines changed

9 files changed

+1169
-27
lines changed

clang/include/clang/AST/Decl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,10 @@ class ValueDecl : public NamedDecl {
732732
bool isInitCapture() const;
733733

734734
/* TO_UPSTREAM(BoundsSafety) ON */
735+
bool isDependentValue() const;
736+
bool isDependentValueWithoutDeref() const;
737+
bool isDependentValueWithDeref() const;
738+
bool isDependentValueThatIsUsedInInoutPointer() const;
735739
/// Whether this decl is a dependent parameter referred to by the return type
736740
/// that is a bounds-attributed type.
737741
bool isDependentParamOfReturnType(

clang/include/clang/AST/TypeBase.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2651,6 +2651,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
26512651
bool isAnyVaListType(ASTContext &) const;
26522652
bool isDynamicRangePointerType() const;
26532653
bool isBoundsAttributedType() const;
2654+
bool isBoundsAttributedTypeDependingOnInoutValue() const;
26542655
bool isValueTerminatedType() const;
26552656
bool isImplicitlyNullTerminatedType(const ASTContext &) const;
26562657
/* TO_UPSTREAM(BoundsSafety) OFF */

clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "clang/AST/Expr.h"
1919
#include "clang/AST/Stmt.h"
2020
#include "clang/Basic/SourceLocation.h"
21+
#include "llvm/ADT/SmallPtrSet.h"
2122
#include "llvm/Support/Debug.h"
2223
#include <set>
2324

@@ -142,6 +143,53 @@ class UnsafeBufferUsageHandler {
142143
ASTContext &Ctx) {
143144
handleUnsafeOperation(Arg, IsRelatedToDecl, Ctx);
144145
}
146+
147+
virtual void handleStandaloneAssign(const Expr *E, const ValueDecl *VD,
148+
bool IsRelatedToDecl, ASTContext &Ctx) {
149+
handleUnsafeOperation(E, IsRelatedToDecl, Ctx);
150+
}
151+
152+
enum class AssignToImmutableObjectKind {
153+
PointerToPointer,
154+
PointerToDependentValue,
155+
PointerDependingOnInoutValue,
156+
DependentValueUsedInInoutPointer,
157+
};
158+
159+
virtual void handleAssignToImmutableObject(const BinaryOperator *Assign,
160+
const ValueDecl *VD,
161+
AssignToImmutableObjectKind Kind,
162+
bool IsRelatedToDecl,
163+
ASTContext &Ctx) {
164+
handleUnsafeOperation(Assign, IsRelatedToDecl, Ctx);
165+
}
166+
167+
virtual void handleMissingAssignments(
168+
const Expr *LastAssignInGroup,
169+
const llvm::SmallPtrSetImpl<const ValueDecl *> &Required,
170+
const llvm::SmallPtrSetImpl<const ValueDecl *> &Missing,
171+
bool IsRelatedToDecl, ASTContext &Ctx) {
172+
handleUnsafeOperation(LastAssignInGroup, IsRelatedToDecl, Ctx);
173+
}
174+
175+
virtual void handleDuplicatedAssignment(const BinaryOperator *Assign,
176+
const BinaryOperator *PrevAssign,
177+
const ValueDecl *VD,
178+
bool IsRelatedToDecl,
179+
ASTContext &Ctx) {
180+
handleUnsafeOperation(Assign, IsRelatedToDecl, Ctx);
181+
}
182+
183+
virtual void handleAssignedAndUsed(const BinaryOperator *Assign,
184+
const Expr *Use, const ValueDecl *VD,
185+
bool IsRelatedToDecl, ASTContext &Ctx) {
186+
handleUnsafeOperation(Assign, IsRelatedToDecl, Ctx);
187+
}
188+
189+
virtual void handleUnsafeCountAttributedPointerAssignment(
190+
const BinaryOperator *Assign, bool IsRelatedToDecl, ASTContext &Ctx) {
191+
handleUnsafeOperation(Assign, IsRelatedToDecl, Ctx);
192+
}
145193
/* TO_UPSTREAM(BoundsSafety) OFF */
146194

147195
/// Invoked when a fix is suggested against a variable. This function groups

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14229,6 +14229,29 @@ def note_unsafe_count_attributed_pointer_argument : Note<
1422914229
def warn_unsafe_single_pointer_argument : Warning<
1423014230
"unsafe assignment to function parameter of __single pointer type">,
1423114231
InGroup<UnsafeBufferUsage>, DefaultIgnore;
14232+
def warn_standalone_assign_to_bounds_attributed_object : Warning<
14233+
"assignment to %select{bounds-attributed pointer|dependent value}0 %1 "
14234+
"must be inside of a bounds-attributed group in a compound statement">,
14235+
InGroup<UnsafeBufferUsage>, DefaultIgnore;
14236+
def warn_cannot_assign_to_immutable_bounds_attributed_object : Warning<
14237+
"cannot assign to %select{variable|parameter|member}0 %1 because %select{"
14238+
"it points to a bounds-attributed pointer|"
14239+
"it points to a dependent value|"
14240+
"its type depends on an inout dependent value|"
14241+
"it's used as dependent value in an inout bounds-attributed pointer"
14242+
"}2">, InGroup<UnsafeBufferUsage>, DefaultIgnore;
14243+
def warn_missing_assignments_in_bounds_attributed_group : Warning<
14244+
"bounds-attributed group requires assigning '%0', assignments to '%1' missing">,
14245+
InGroup<UnsafeBufferUsage>, DefaultIgnore;
14246+
def warn_duplicated_assignment_in_bounds_attributed_group : Warning<
14247+
"duplicated assignment to %select{variable|parameter|member}0 %1 in "
14248+
"bounds-attributed group">, InGroup<UnsafeBufferUsage>, DefaultIgnore;
14249+
def warn_assigned_and_used_in_bounds_attributed_group : Warning<
14250+
"%select{variable|parameter|member}0 %1 is assigned and used in the same "
14251+
"bounds-attributed group">, InGroup<UnsafeBufferUsage>, DefaultIgnore;
14252+
def warn_unsafe_count_attributed_pointer_assignment : Warning<
14253+
"unsafe assignment to count-attributed pointer">,
14254+
InGroup<UnsafeBufferUsage>, DefaultIgnore;
1423214255
#ifndef NDEBUG
1423314256
// Not a user-facing diagnostic. Useful for debugging false negatives in
1423414257
// -fsafe-buffer-usage-suggestions (i.e. lack of -Wunsafe-buffer-usage fixits).

clang/lib/AST/Decl.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5502,6 +5502,27 @@ bool ValueDecl::isParameterPack() const {
55025502
}
55035503

55045504
/* TO_UPSTREAM(BoundsSafety) ON */
5505+
bool ValueDecl::isDependentValue() const {
5506+
return hasAttr<DependerDeclsAttr>();
5507+
}
5508+
5509+
bool ValueDecl::isDependentValueWithoutDeref() const {
5510+
const auto *Att = getAttr<DependerDeclsAttr>();
5511+
return Att && !Att->getIsDeref();
5512+
}
5513+
5514+
bool ValueDecl::isDependentValueWithDeref() const {
5515+
const auto *Att = getAttr<DependerDeclsAttr>();
5516+
return Att && Att->getIsDeref();
5517+
}
5518+
5519+
bool ValueDecl::isDependentValueThatIsUsedInInoutPointer() const {
5520+
const auto *Att = getAttr<DependerDeclsAttr>();
5521+
return Att &&
5522+
std::any_of(Att->dependerLevels_begin(), Att->dependerLevels_end(),
5523+
[](unsigned Level) { return Level > 0; });
5524+
}
5525+
55055526
bool ValueDecl::isDependentParamOfReturnType(
55065527
const BoundsAttributedType **RetType,
55075528
const TypeCoupledDeclRefInfo **Info) const {

clang/lib/AST/Type.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,14 @@ bool Type::isBoundsAttributedType() const {
829829
return getAs<BoundsAttributedType>();
830830
}
831831

832+
bool Type::isBoundsAttributedTypeDependingOnInoutValue() const {
833+
const auto *BAT = getAs<BoundsAttributedType>();
834+
return BAT &&
835+
std::any_of(
836+
BAT->dependent_decl_begin(), BAT->dependent_decl_end(),
837+
[](const TypeCoupledDeclRefInfo &Info) { return Info.isDeref(); });
838+
}
839+
832840
bool Type::isValueTerminatedType() const {
833841
return getAs<ValueTerminatedType>();
834842
}

0 commit comments

Comments
 (0)