Skip to content

Commit c6d8a58

Browse files
author
MalavikaSamak
committed
[-Wunsafe-buffer-usage] Fix false warnings when const array is safely accessed array [idx %const]
The -Wunsafe-buffer-usage analysis currently warns when a const sized array is safely accessed, with an index that is bound by the remainder operator. The false alarm is now suppressed. Example: int circular_buffer(int array[10], uint idx) { return array[idx %10]; // Safe operation } rdar://148443453
1 parent 8b53ada commit c6d8a58

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

clang/lib/Analysis/UnsafeBufferUsage.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,12 +600,27 @@ static bool isSafeArraySubscript(const ArraySubscriptExpr &Node,
600600
} else if (const auto *BE = dyn_cast<BinaryOperator>(IndexExpr)) {
601601
// For an integer expression `e` and an integer constant `n`, `e & n` and
602602
// `n & e` are bounded by `n`:
603-
if (BE->getOpcode() != BO_And)
603+
if (BE->getOpcode() != BO_And && BE->getOpcode() != BO_Rem)
604604
return false;
605605

606606
const Expr *LHS = BE->getLHS();
607607
const Expr *RHS = BE->getRHS();
608608

609+
if(BE->getOpcode() == BO_Rem) {
610+
// If n is a negative number, then n % const can be greater than const
611+
if(!LHS->getType()->isUnsignedIntegerType()) {
612+
return false;
613+
}
614+
615+
if(!RHS->isValueDependent() && RHS->EvaluateAsInt(EVResult, Ctx)) {
616+
llvm::APSInt result = EVResult.Val.getInt();
617+
if (result.isNonNegative() && result.getLimitedValue() <= limit)
618+
return true;
619+
}
620+
621+
return false;
622+
}
623+
609624
if ((!LHS->isValueDependent() &&
610625
LHS->EvaluateAsInt(EVResult, Ctx)) || // case: `n & e`
611626
(!RHS->isValueDependent() &&

clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,15 @@ void constant_idx_safe0(unsigned idx) {
3535
buffer[0] = 0;
3636
}
3737

38-
int array[10]; // expected-warning {{'array' is an unsafe buffer that does not perform bounds checks}}
38+
int array[10]; // expected-warning 2{{'array' is an unsafe buffer that does not perform bounds checks}}
39+
40+
void circular_access_safe(unsigned idx) {
41+
array[idx % 10];
42+
}
43+
44+
void circular_access_unsafe(int idx) {
45+
array[idx % 10]; // expected-note {{used in buffer access here}}
46+
}
3947

4048
void masked_idx1(unsigned long long idx, Foo f) {
4149
// Bitwise and operation

0 commit comments

Comments
 (0)