Skip to content

Commit 4ac4822

Browse files
Merge pull request swiftlang#9619 from swiftlang/msamak-cherrypick-fp-stringliterals
[Cherry-Pick][Wunsafe-buffer-usage] Fix false positives in handling string literals. (llvm#115552)
2 parents 3e6d27e + da45757 commit 4ac4822

File tree

2 files changed

+33
-9
lines changed

2 files changed

+33
-9
lines changed

clang/lib/Analysis/UnsafeBufferUsage.cpp

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -436,21 +436,31 @@ AST_MATCHER(ArraySubscriptExpr, isSafeArraySubscript) {
436436

437437
const auto *BaseDRE =
438438
dyn_cast<DeclRefExpr>(Node.getBase()->IgnoreParenImpCasts());
439-
if (!BaseDRE)
440-
return false;
441-
if (!BaseDRE->getDecl())
442-
return false;
443-
const auto *CATy = Finder->getASTContext().getAsConstantArrayType(
444-
BaseDRE->getDecl()->getType());
445-
if (!CATy)
439+
const auto *SLiteral =
440+
dyn_cast<StringLiteral>(Node.getBase()->IgnoreParenImpCasts());
441+
uint64_t size;
442+
443+
if (!BaseDRE && !SLiteral)
446444
return false;
447445

446+
if (BaseDRE) {
447+
if (!BaseDRE->getDecl())
448+
return false;
449+
const auto *CATy = Finder->getASTContext().getAsConstantArrayType(
450+
BaseDRE->getDecl()->getType());
451+
if (!CATy) {
452+
return false;
453+
}
454+
size = CATy->getLimitedSize();
455+
} else if (SLiteral) {
456+
size = SLiteral->getLength() + 1;
457+
}
458+
448459
if (const auto *IdxLit = dyn_cast<IntegerLiteral>(Node.getIdx())) {
449460
const APInt ArrIdx = IdxLit->getValue();
450461
// FIXME: ArrIdx.isNegative() we could immediately emit an error as that's a
451462
// bug
452-
if (ArrIdx.isNonNegative() &&
453-
ArrIdx.getLimitedValue() < CATy->getLimitedSize())
463+
if (ArrIdx.isNonNegative() && ArrIdx.getLimitedValue() < size)
454464
return true;
455465
}
456466

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,17 @@ void constant_idx_unsafe(unsigned idx) {
3838
// expected-note@-1{{change type of 'buffer' to 'std::array' to label it for hardening}}
3939
buffer[10] = 0; // expected-note{{used in buffer access here}}
4040
}
41+
42+
void constant_id_string(unsigned idx) {
43+
char safe_char = "abc"[1]; // no-warning
44+
safe_char = ""[0];
45+
safe_char = "\0"[0];
46+
47+
char abcd[5] = "abc";
48+
abcd[2]; // no-warning
49+
50+
char unsafe_char = "abc"[3];
51+
unsafe_char = "abc"[-1]; //expected-warning{{unsafe buffer access}}
52+
unsafe_char = ""[1]; //expected-warning{{unsafe buffer access}}
53+
unsafe_char = ""[idx]; //expected-warning{{unsafe buffer access}}
54+
}

0 commit comments

Comments
 (0)