diff options
| -rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 28 | ||||
| -rw-r--r-- | clang/test/Sema/warn-strlcpycat-size.c | 27 |
2 files changed, 45 insertions, 10 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 882668e5151..82c97a63cdb 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2071,18 +2071,26 @@ void Sema::CheckStrlcpycatArguments(const CallExpr *Call, // pointers if we know the actual size, like if DstArg is 'array+2' // we could say 'sizeof(array)-2'. const Expr *DstArg = Call->getArg(0)->IgnoreParenImpCasts(); + QualType DstArgTy = DstArg->getType(); - if (DstArg->getType()->isArrayType()) { - llvm::SmallString<128> sizeString; - llvm::raw_svector_ostream OS(sizeString); - OS << "sizeof("; - DstArg->printPretty(OS, Context, 0, Context.PrintingPolicy); - OS << ")"; - - Diag(OriginalSizeArg->getLocStart(), diag::note_strlcpycat_wrong_size) - << FixItHint::CreateReplacement(OriginalSizeArg->getSourceRange(), - OS.str()); + // Only handle constant-sized or VLAs, but not flexible members. + if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(DstArgTy)) { + // Only issue the FIXIT for arrays of size > 1. + if (CAT->getSize().getSExtValue() <= 1) + return; + } else if (!DstArgTy->isVariableArrayType()) { + return; } + + llvm::SmallString<128> sizeString; + llvm::raw_svector_ostream OS(sizeString); + OS << "sizeof("; + DstArg->printPretty(OS, Context, 0, Context.PrintingPolicy); + OS << ")"; + + Diag(OriginalSizeArg->getLocStart(), diag::note_strlcpycat_wrong_size) + << FixItHint::CreateReplacement(OriginalSizeArg->getSourceRange(), + OS.str()); } //===--- CHECK: Return Address of Stack Variable --------------------------===// diff --git a/clang/test/Sema/warn-strlcpycat-size.c b/clang/test/Sema/warn-strlcpycat-size.c index e9e617488c4..34830120d5d 100644 --- a/clang/test/Sema/warn-strlcpycat-size.c +++ b/clang/test/Sema/warn-strlcpycat-size.c @@ -26,3 +26,30 @@ void f(void) strlcpy((*s5)->f2[x], s2, sizeof(s2)); // expected-warning {{size argument in 'strlcpy' call appears to be size of the source; expected the size of the destination}} expected-note {{change size argument to be the size of the destination}} strlcpy(s1+3, s2, sizeof(s2)); // expected-warning {{size argument in 'strlcpy' call appears to be size of the source; expected the size of the destination}} } + +// Don't issue FIXIT for flexible arrays. +struct S { + int y; + char x[]; +}; + +void flexible_arrays(struct S *s) { + char str[] = "hi"; + strlcpy(s->x, str, sizeof(str)); // expected-warning {{size argument in 'strlcpy' call appears to be size of the source; expected the size of the destination}} +} + +// Don't issue FIXIT for destinations of size 1. +void size_1() { + char z[1]; + char str[] = "hi"; + + strlcpy(z, str, sizeof(str)); // expected-warning {{size argument in 'strlcpy' call appears to be size of the source; expected the size of the destination}} +} + +// Support VLAs. +void vlas(int size) { + char z[size]; + char str[] = "hi"; + + strlcpy(z, str, sizeof(str)); // expected-warning {{size argument in 'strlcpy' call appears to be size of the source; expected the size of the destination}} expected-note {{change size argument to be the size of the destination}} +} |

