Skip to content

Commit 9d2b87d

Browse files
committed
[Bounds-Safety] restrict sized_by for types w/o size unless incomplete
Emit an error when sized_by or sized_by_or_null is used on sizeless types, function pointers and pointers to structs with flexible array members. Although we *could* track their size, it is not useful and indexing would not work.
1 parent eb4e65b commit 9d2b87d

10 files changed

+32
-5
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6588,7 +6588,7 @@ def err_count_attr_refer_to_union : Error<
65886588
def note_flexible_array_counted_by_attr_field : Note<
65896589
"field %0 declared here">;
65906590
def err_counted_by_attr_pointee_unknown_size : Error<
6591-
"'%select{counted_by|counted_by_or_null}4' %select{cannot|should not}3 be applied to %select{"
6591+
"'%select{counted_by|sized_by|counted_by_or_null|sized_by_or_null}4' %select{cannot|should not}3 be applied to %select{"
65926592
"a pointer with pointee|" // pointer
65936593
"an array with element}0" // array
65946594
" of unknown size because %1 is %select{"

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5941,7 +5941,7 @@ CheckCountedByAttrOnField(Sema &S, FieldDecl *FD, Expr *E,
59415941
// only `PointeeTy->isStructureTypeWithFlexibleArrayMember()` is reachable
59425942
// when `FieldTy->isArrayType()`.
59435943
bool ShouldWarn = false;
5944-
if (PointeeTy->isIncompleteType()) {
5944+
if (PointeeTy->isIncompleteType() && !CountInBytes) {
59455945
InvalidTypeKind = CountedByInvalidPointeeTypeKind::INCOMPLETE;
59465946
} else if (PointeeTy->isSizelessType()) {
59475947
InvalidTypeKind = CountedByInvalidPointeeTypeKind::SIZELESS;
@@ -5960,14 +5960,13 @@ CheckCountedByAttrOnField(Sema &S, FieldDecl *FD, Expr *E,
59605960
InvalidTypeKind = CountedByInvalidPointeeTypeKind::FLEXIBLE_ARRAY_MEMBER;
59615961
}
59625962

5963-
if (InvalidTypeKind != CountedByInvalidPointeeTypeKind::VALID &&
5964-
!CountInBytes) {
5963+
if (InvalidTypeKind != CountedByInvalidPointeeTypeKind::VALID) {
59655964
unsigned DiagID = ShouldWarn
59665965
? diag::warn_counted_by_attr_elt_type_unknown_size
59675966
: diag::err_counted_by_attr_pointee_unknown_size;
59685967
S.Diag(FD->getBeginLoc(), DiagID)
59695968
<< SelectPtrOrArr << PointeeTy << (int)InvalidTypeKind
5970-
<< (ShouldWarn ? 1 : 0) << OrNull << FD->getSourceRange();
5969+
<< (ShouldWarn ? 1 : 0) << Kind << FD->getSourceRange();
59715970
return true;
59725971
}
59735972

clang/test/Sema/attr-sized-by-last-field.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,5 +137,6 @@ struct on_member_ptr_fn_ptr_ty {
137137

138138
struct on_member_ptr_fn_ty {
139139
int size;
140+
// expected-error@+1{{'sized_by' cannot be applied to a pointer with pointee of unknown size because 'fn_ty' (aka 'void (int)') is a function type}}
140141
fn_ty * ptr __sized_by(size);
141142
};

clang/test/Sema/attr-sized-by-late-parsed-struct-ptrs.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,14 @@ struct on_member_pointer_fn_ptr_ty_ptr_ty {
4848

4949
struct on_member_pointer_fn_ty {
5050
// buffer of function(s) with size `size` is allowed
51+
// expected-error@+1{{'sized_by' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}}
5152
void (*fn_ptr)(void) __sized_by(size);
5253
int size;
5354
};
5455

5556
struct on_member_pointer_fn_ptr_ty_ty {
5657
// buffer of function(s) with size `size` is allowed
58+
// expected-error@+1{{'sized_by' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}}
5759
fn_ptr_ty fn_ptr __sized_by(size);
5860
int size;
5961
};
@@ -64,6 +66,7 @@ struct has_unannotated_vla {
6466
};
6567

6668
struct on_member_pointer_struct_with_vla {
69+
// expected-error@+1{{'sized_by' cannot be applied to a pointer with pointee of unknown size because 'struct has_unannotated_vla' is a struct type with a flexible array member}}
6770
struct has_unannotated_vla* objects __sized_by(size);
6871
int size;
6972
};
@@ -75,6 +78,7 @@ struct has_annotated_vla {
7578
};
7679

7780
struct on_member_pointer_struct_with_annotated_vla {
81+
// expected-error@+1{{'sized_by' cannot be applied to a pointer with pointee of unknown size because 'struct has_annotated_vla' is a struct type with a flexible array member}}
7882
struct has_annotated_vla* objects __sized_by(size);
7983
int size;
8084
};

clang/test/Sema/attr-sized-by-or-null-last-field.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,5 +137,6 @@ struct on_member_ptr_fn_ptr_ty {
137137

138138
struct on_member_ptr_fn_ty {
139139
int size;
140+
// expected-error@+1{{'sized_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'fn_ty' (aka 'void (int)') is a function type}}
140141
fn_ty * ptr __sized_by_or_null(size);
141142
};

clang/test/Sema/attr-sized-by-or-null-late-parsed-struct-ptrs.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,14 @@ struct on_member_pointer_fn_ptr_ty_ptr_ty {
4848

4949
struct on_member_pointer_fn_ty {
5050
// buffer of function(s) with size `size` is allowed
51+
// expected-error@+1{{'sized_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}}
5152
void (*fn_ptr)(void) __sized_by_or_null(size);
5253
int size;
5354
};
5455

5556
struct on_member_pointer_fn_ptr_ty_ty {
5657
// buffer of function(s) with size `size` is allowed
58+
// expected-error@+1{{'sized_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}}
5759
fn_ptr_ty fn_ptr __sized_by_or_null(size);
5860
int size;
5961
};
@@ -64,6 +66,7 @@ struct has_unannotated_vla {
6466
};
6567

6668
struct on_member_pointer_struct_with_vla {
69+
// expected-error@+1{{'sized_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'struct has_unannotated_vla' is a struct type with a flexible array member}}
6770
struct has_unannotated_vla* objects __sized_by_or_null(size);
6871
int size;
6972
};
@@ -75,6 +78,7 @@ struct has_annotated_vla {
7578
};
7679

7780
struct on_member_pointer_struct_with_annotated_vla {
81+
// expected-error@+1{{'sized_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'struct has_annotated_vla' is a struct type with a flexible array member}}
7882
struct has_annotated_vla* objects __sized_by_or_null(size);
7983
int size;
8084
};

clang/test/Sema/attr-sized-by-or-null-struct-ptrs-sizeless-types.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
struct on_sizeless_pointee_ty {
77
int size;
8+
// expected-error@+1{{'sized_by_or_null' cannot be applied to a pointer with pointee of unknown size because '__SVInt8_t' is a sizeless type}}
89
__SVInt8_t* member __sized_by_or_null(size);
910
};
1011

clang/test/Sema/attr-sized-by-or-null-struct-ptrs.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,14 @@ struct on_member_pointer_fn_ptr_ty_ptr_ty {
4949
struct on_member_pointer_fn_ty {
5050
int size;
5151
// buffer of functions with size `size` is allowed
52+
// expected-error@+1{{'sized_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}}
5253
void (*fn_ptr)(void) __sized_by_or_null(size);
5354
};
5455

5556
struct on_member_pointer_fn_ptr_ty_ty {
5657
int size;
5758
// buffer of functions with size `size` is allowed
59+
// expected-error@+1{{'sized_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}}
5860
fn_ptr_ty fn_ptr __sized_by_or_null(size);
5961
};
6062

@@ -66,6 +68,7 @@ struct has_unannotated_vla {
6668
struct on_member_pointer_struct_with_vla {
6769
int size;
6870
// we know the size so this is fine for tracking size, however indexing would be an issue
71+
// expected-error@+1{{'sized_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'struct has_unannotated_vla' is a struct type with a flexible array member}}
6972
struct has_unannotated_vla* objects __sized_by_or_null(size);
7073
};
7174

@@ -77,6 +80,7 @@ struct has_annotated_vla {
7780
struct on_member_pointer_struct_with_annotated_vla {
7881
int size;
7982
// we know the size so this is fine for tracking size, however indexing would be an issue
83+
// expected-error@+1{{'sized_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'struct has_annotated_vla' is a struct type with a flexible array member}}
8084
struct has_annotated_vla* objects __sized_by_or_null(size);
8185
};
8286

@@ -136,11 +140,13 @@ struct on_member_pointer_fn_ptr_ty_ptr_ty_pos {
136140

137141
struct on_member_pointer_fn_ty_ty_pos {
138142
int size;
143+
// expected-error@+1{{'sized_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}}
139144
void (* __sized_by_or_null(size) fn_ptr)(void);
140145
};
141146

142147
struct on_member_pointer_fn_ptr_ty_ty_pos {
143148
int size;
149+
// expected-error@+1{{'sized_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}}
144150
fn_ptr_ty __sized_by_or_null(size) fn_ptr;
145151
};
146152

@@ -153,11 +159,13 @@ struct on_member_pointer_fn_ptr_ty_ty_pos_inner {
153159

154160
struct on_member_pointer_struct_with_vla_ty_pos {
155161
int size;
162+
// expected-error@+1{{'sized_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'struct has_unannotated_vla' is a struct type with a flexible array member}}
156163
struct has_unannotated_vla *__sized_by_or_null(size) objects;
157164
};
158165

159166
struct on_member_pointer_struct_with_annotated_vla_ty_pos {
160167
int size;
168+
// expected-error@+1{{'sized_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'struct has_annotated_vla' is a struct type with a flexible array member}}
161169
struct has_annotated_vla* __sized_by_or_null(size) objects;
162170
};
163171

clang/test/Sema/attr-sized-by-struct-ptrs-sizeless-types.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
struct on_sizeless_pointee_ty {
77
int count;
8+
// expected-error@+1{{'sized_by' cannot be applied to a pointer with pointee of unknown size because '__SVInt8_t' is a sizeless type}}
89
__SVInt8_t* member __sized_by(count);
910
};
1011

clang/test/Sema/attr-sized-by-struct-ptrs.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,14 @@ struct on_member_pointer_fn_ptr_ty_ptr_ty {
4949
struct on_member_pointer_fn_ty {
5050
int size;
5151
// buffer of functions with size `size` is allowed
52+
// expected-error@+1{{'sized_by' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}}
5253
void (*fn_ptr)(void) __sized_by(size);
5354
};
5455

5556
struct on_member_pointer_fn_ptr_ty_ty {
5657
int size;
5758
// buffer of functions with size `size` is allowed
59+
// expected-error@+1{{'sized_by' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}}
5860
fn_ptr_ty fn_ptr __sized_by(size);
5961
};
6062

@@ -66,6 +68,7 @@ struct has_unannotated_vla {
6668
struct on_member_pointer_struct_with_vla {
6769
int size;
6870
// we know the size so this is fine for tracking size, however indexing would be an issue
71+
// expected-error@+1{{'sized_by' cannot be applied to a pointer with pointee of unknown size because 'struct has_unannotated_vla' is a struct type with a flexible array member}}
6972
struct has_unannotated_vla* objects __sized_by(size);
7073
};
7174

@@ -77,6 +80,7 @@ struct has_annotated_vla {
7780
struct on_member_pointer_struct_with_annotated_vla {
7881
int size;
7982
// we know the size so this is fine for tracking size, however indexing would be an issue
83+
// expected-error@+1{{'sized_by' cannot be applied to a pointer with pointee of unknown size because 'struct has_annotated_vla' is a struct type with a flexible array member}}
8084
struct has_annotated_vla* objects __sized_by(size);
8185
};
8286

@@ -136,11 +140,13 @@ struct on_member_pointer_fn_ptr_ty_ptr_ty_pos {
136140

137141
struct on_member_pointer_fn_ty_ty_pos {
138142
int size;
143+
// expected-error@+1{{'sized_by' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}}
139144
void (* __sized_by(size) fn_ptr)(void);
140145
};
141146

142147
struct on_member_pointer_fn_ptr_ty_ty_pos {
143148
int size;
149+
// expected-error@+1{{'sized_by' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}}
144150
fn_ptr_ty __sized_by(size) fn_ptr;
145151
};
146152

@@ -153,11 +159,13 @@ struct on_member_pointer_fn_ptr_ty_ty_pos_inner {
153159

154160
struct on_member_pointer_struct_with_vla_ty_pos {
155161
int size;
162+
// expected-error@+1{{'sized_by' cannot be applied to a pointer with pointee of unknown size because 'struct has_unannotated_vla' is a struct type with a flexible array member}}
156163
struct has_unannotated_vla *__sized_by(size) objects;
157164
};
158165

159166
struct on_member_pointer_struct_with_annotated_vla_ty_pos {
160167
int size;
168+
// expected-error@+1{{'sized_by' cannot be applied to a pointer with pointee of unknown size because 'struct has_annotated_vla' is a struct type with a flexible array member}}
161169
struct has_annotated_vla* __sized_by(size) objects;
162170
};
163171

0 commit comments

Comments
 (0)