Index: lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp +++ lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp @@ -510,6 +510,18 @@ if (!checkCall_strCommon(CE, FD)) return; + int ArraySize = -1, StrLen = -1; + const auto *Target = CE->getArg(0)->IgnoreImpCasts(), + *Source = CE->getArg(1)->IgnoreImpCasts(); + if (const auto *DeclRef = dyn_cast(Target)) + if (const auto *Array = dyn_cast( + DeclRef->getDecl()->getType().getTypePtr())) + ArraySize = Array->getSize().getLimitedValue(); + if (const auto *String = dyn_cast(Source)) + StrLen = String->getLength(); + if (StrLen != -1 && ArraySize >= StrLen + 1) + return; + // Issue a warning. PathDiagnosticLocation CELoc = PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC); Index: test/Analysis/security-syntax-checks-no-emit.c =================================================================== --- test/Analysis/security-syntax-checks-no-emit.c +++ test/Analysis/security-syntax-checks-no-emit.c @@ -32,3 +32,31 @@ rand_r(&b); // no-warning random(); // no-warning } + +#ifdef USE_BUILTINS +#define BUILTIN(f) __builtin_##f +#else /* USE_BUILTINS */ +#define BUILTIN(f) f +#endif /* USE_BUILTINS */ + +//===----------------------------------------------------------------------=== +// strcpy() +//===----------------------------------------------------------------------=== +#ifdef VARIANT + +#define __strcpy_chk BUILTIN(__strcpy_chk) +char *__strcpy_chk(char *restrict s1, const char *restrict s2, size_t destlen); + +#define strcpy(a, b) __strcpy_chk(a, b, (size_t)-1) + +#else /* VARIANT */ + +#define strcpy BUILTIN(strcpy) +char *strcpy(char *restrict s1, const char *restrict s2); + +#endif /* VARIANT */ + +void test_strcpy() { + char x[5]; + strcpy(x, "abcd"); +}