Skip to content

Commit 1c9cc8d

Browse files
[-Wunsafe-buffer-usage] Relax passing to __counted_by_or_null()
Relax restrictions when passing to __counted_by_or_null()/__sized_by_or_null() parameters: - Allow the dependent count var to be anything. - Allow passing from non-null variant to *_or_null(), but do warn for passing *_or_null() to non-null variant. rdar://156006635
1 parent f539fb5 commit 1c9cc8d

File tree

2 files changed

+50
-6
lines changed

2 files changed

+50
-6
lines changed

clang/lib/Analysis/UnsafeBufferUsage.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -875,7 +875,9 @@ static const DeclRefExpr *tryGetAddressofDRE(const Expr *E) {
875875

876876
// Checks if the argument passed to count-attributed pointer is one of the
877877
// following forms:
878-
// 0. `NULL/nullptr`, if the argument to dependent count/size is `0`.
878+
// 0. `NULL/nullptr`, if the argument to dependent count/size is `0`, or
879+
// anything if the type of the pointer is
880+
// __counted_by_or_null()/__sized_by_or_null().
879881
// 1. `&var`, if `var` is a variable identifier and (1.a.) the dependent count
880882
// is `1`; or (1.b.) the counted_by expression is constant `1`
881883
// 2. `&var`, if `var` is a variable identifier and the dependent size is
@@ -935,6 +937,8 @@ static bool isCountAttributedPointerArgumentSafeImpl(
935937

936938
// check form 0:
937939
if (PtrArgNoImp->getType()->isNullPtrType()) {
940+
if (isOrNull)
941+
return true;
938942
if (CountArg)
939943
return hasIntegeralConstant(CountArg, 0, Context);
940944
// When there is no argument representing the count/size, it is safe iff
@@ -1005,7 +1009,7 @@ static bool isCountAttributedPointerArgumentSafeImpl(
10051009
bool areBoundsAttributesCompatible =
10061010
(ArgCAT->isCountInBytes() == isSizedBy || (ArgInBytes && ParamInBytes));
10071011

1008-
if (ArgCAT->isOrNull() == isOrNull && areBoundsAttributesCompatible)
1012+
if ((isOrNull || !ArgCAT->isOrNull()) && areBoundsAttributesCompatible)
10091013
ActualCount = ArgCAT->getCountExpr();
10101014
} else {
10111015
// Form 6-7.

clang/test/SemaCXX/warn-unsafe-buffer-usage-count-attributed-pointer-argument.cpp

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ void cb_cchar(const char *__counted_by(len) s, size_t len);
6969
// expected-note@+1 3{{consider using 'std::span' and passing '.first(...).data()' to the parameter 's'}}
7070
void cb_cchar_42(const char *__counted_by(42) s);
7171

72-
// expected-note@+1 19{{consider using a safe container and passing '.data()' to the parameter 'p' and '.size()' to its dependent parameter 'count' or 'std::span' and passing '.first(...).data()' to the parameter 'p'}}
72+
// expected-note@+1 22{{consider using a safe container and passing '.data()' to the parameter 'p' and '.size()' to its dependent parameter 'count' or 'std::span' and passing '.first(...).data()' to the parameter 'p'}}
7373
void cb_int(int *__counted_by(count) p, size_t count);
7474

7575
// expected-note@+1 34{{consider using a safe container and passing '.data()' to the parameter 'p' and '.size()' to its dependent parameter 'count' or 'std::span' and passing '.first(...).data()' to the parameter 'p'}}
@@ -81,6 +81,9 @@ void cb_cint_42(const int *__counted_by(42) p);
8181
// expected-note@+1 6{{consider using 'std::span' and passing '.first(...).data()' to the parameter 'p'}}
8282
void cb_cint_multi(const int *__counted_by((a + b) * (c - d)) p, int a, int b, int c, int d);
8383

84+
// expected-note@+1 3{{consider using a safe container and passing '.data()' to the parameter 'p' and '.size()' to its dependent parameter 'size' or 'std::span' and passing '.first(...).data()' to the parameter 'p'}}
85+
void sb_void(void *__sized_by(size) p, size_t size);
86+
8487
// expected-note@+1 13{{consider using a safe container and passing '.data()' to the parameter 'p' and '.size()' to its dependent parameter 'size' or 'std::span' and passing '.first(...).data()' to the parameter 'p'}}
8588
void sb_cvoid(const void *__sized_by(size) p, size_t size);
8689

@@ -98,6 +101,10 @@ void sb_cint_42(const int *__sized_by(42) p);
98101

99102
void cb_cint_array(const int (* __counted_by(size) p)[10], size_t size);
100103

104+
void cbn_int(int *__counted_by_or_null(count) p, size_t count);
105+
106+
void sbn_void(void *__sized_by_or_null(size) p, size_t size);
107+
101108
} // extern "C"
102109

103110
// Check allowed classes and method.
@@ -389,9 +396,22 @@ void from_cb_int_multi(int *__counted_by((a + b) * (c - d)) p, int a, int b, int
389396
cb_int(p, 42); // expected-warning{{unsafe assignment to function parameter of count-attributed type}}
390397
}
391398

392-
void nullptr_as_arg(void * __sized_by(size) p, unsigned size) { //expected-note{{consider using a safe container and passing '.data()' to the parameter 'p' and '.size()' to its dependent parameter 'size' or 'std::span' and passing '.first(...).data()' to the parameter 'p'}}
393-
nullptr_as_arg(nullptr, 0);
394-
nullptr_as_arg(nullptr, size); // expected-warning{{unsafe assignment to function parameter of count-attributed type}}
399+
void nullptr_as_arg(size_t n) {
400+
cb_int(nullptr, 0);
401+
cb_int(nullptr, 42); // expected-warning{{unsafe assignment to function parameter of count-attributed type}}
402+
cb_int(nullptr, n); // expected-warning{{unsafe assignment to function parameter of count-attributed type}}
403+
404+
sb_void(nullptr, 0);
405+
sb_void(nullptr, 42); // expected-warning{{unsafe assignment to function parameter of count-attributed type}}
406+
sb_void(nullptr, n); // expected-warning{{unsafe assignment to function parameter of count-attributed type}}
407+
408+
cbn_int(nullptr, 0);
409+
cbn_int(nullptr, 42);
410+
cbn_int(nullptr, n);
411+
412+
sbn_void(nullptr, 0);
413+
sbn_void(nullptr, 42);
414+
sbn_void(nullptr, n);
395415
}
396416

397417
void single_variable() {
@@ -664,3 +684,23 @@ static void previous_infinite_loop3(int * __counted_by(n + n * m) p, size_t n,
664684
previous_infinite_loop3(p, n, q, r, m, o);
665685
previous_infinite_loop3(p, n, q, r, m, o + 1); // expected-warning 2{{unsafe assignment to function parameter of count-attributed type}}
666686
}
687+
688+
// Check nullable variants.
689+
690+
void nonnull_tofrom_nullable(size_t n,
691+
int *__counted_by(n) cb,
692+
int *__counted_by_or_null(n) cbn,
693+
void *__sized_by(n) sb,
694+
void *__sized_by_or_null(n) sbn) {
695+
cb_int(cb, n);
696+
cb_int(cbn, n); // expected-warning{{unsafe assignment to function parameter of count-attributed type}}
697+
698+
cbn_int(cb, n);
699+
cbn_int(cbn, n);
700+
701+
sb_void(sb, n);
702+
sb_void(sbn, n); // expected-warning{{unsafe assignment to function parameter of count-attributed type}}
703+
704+
sbn_void(sb, n);
705+
sbn_void(sbn, n);
706+
}

0 commit comments

Comments
 (0)