leanil created this revision.
leanil added reviewers: dcoughlin, xazax.hun.
Herald added subscribers: a.sidorin, rnkovacs, szepet.

It is safe to copy a string literal to an array which is compile time known to 
be large enough.
This reduces the number of false positives, while (hopefully) not introducing 
any false negatives.


https://reviews.llvm.org/D41384

Files:
  lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
  test/Analysis/security-syntax-checks-no-emit.c


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");
+}
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<DeclRefExpr>(Target))
+    if (const auto *Array = dyn_cast<ConstantArrayType>(
+            DeclRef->getDecl()->getType().getTypePtr()))
+      ArraySize = Array->getSize().getLimitedValue();
+  if (const auto *String = dyn_cast<StringLiteral>(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");
+}
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<DeclRefExpr>(Target))
+    if (const auto *Array = dyn_cast<ConstantArrayType>(
+            DeclRef->getDecl()->getType().getTypePtr()))
+      ArraySize = Array->getSize().getLimitedValue();
+  if (const auto *String = dyn_cast<StringLiteral>(Source))
+    StrLen = String->getLength();
+  if (StrLen != -1 && ArraySize >= StrLen + 1)
+    return;
+
   // Issue a warning.
   PathDiagnosticLocation CELoc =
     PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to