steakhal updated this revision to Diff 435611.
steakhal marked 2 inline comments as done.
steakhal added a comment.

- Use `assert` macro for introducing constraints.
- Add tests for store binding invalidations, besides constraint invalidations.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D127306/new/

https://reviews.llvm.org/D127306

Files:
  clang/lib/StaticAnalyzer/Core/MemRegion.cpp
  clang/test/Analysis/Inputs/some_system_globals.h
  clang/test/Analysis/Inputs/some_user_globals.h
  clang/test/Analysis/global-region-invalidation.c
  clang/test/Analysis/globals-are-not-always-immutable.c

Index: clang/test/Analysis/globals-are-not-always-immutable.c
===================================================================
--- /dev/null
+++ clang/test/Analysis/globals-are-not-always-immutable.c
@@ -0,0 +1,71 @@
+// RUN: %clang_analyze_cc1 -verify %s \
+// RUN:   -analyzer-config eagerly-assume=false \
+// RUN:   -analyzer-checker=core,debug.ExprInspection
+
+#include "Inputs/errno_var.h"
+#include "Inputs/some_system_globals.h"
+#include "Inputs/some_user_globals.h"
+
+extern void abort() __attribute__((__noreturn__));
+#define assert(expr) ((expr) ? (void)(0) : abort())
+
+void invalidate_globals(void);
+void clang_analyzer_eval(int x);
+
+/// Test the special system 'errno'
+void test_errno_constraint() {
+  assert(errno > 2);
+  clang_analyzer_eval(errno > 2); // expected-warning {{TRUE}}
+  invalidate_globals();
+  clang_analyzer_eval(errno > 2); // expected-warning {{UNKNOWN}}
+}
+void test_errno_assign(int x) {
+  errno = x;
+  clang_analyzer_eval(errno == x); // expected-warning {{TRUE}}
+  invalidate_globals();
+  clang_analyzer_eval(errno == x); // expected-warning {{UNKNOWN}}
+}
+
+/// Test user global variables
+void test_my_const_user_global_constraint() {
+  assert(my_const_user_global > 2);
+  clang_analyzer_eval(my_const_user_global > 2); // expected-warning {{TRUE}}
+  invalidate_globals();
+  clang_analyzer_eval(my_const_user_global > 2); // expected-warning {{TRUE}}
+}
+void test_my_const_user_global_assign(int); // One cannot assign value to a const lvalue.
+
+void test_my_mutable_user_global_constraint() {
+  assert(my_mutable_user_global > 2);
+  clang_analyzer_eval(my_mutable_user_global > 2); // expected-warning {{TRUE}}
+  invalidate_globals();
+  clang_analyzer_eval(my_mutable_user_global > 2); // expected-warning {{UNKNOWN}}
+}
+void test_my_mutable_user_global_assign(int x) {
+  my_mutable_user_global = x;
+  clang_analyzer_eval(my_mutable_user_global == x); // expected-warning {{TRUE}}
+  invalidate_globals();
+  clang_analyzer_eval(my_mutable_user_global == x); // expected-warning {{UNKNOWN}}
+}
+
+/// Test system global variables
+void test_my_const_system_global_constraint() {
+  assert(my_const_system_global > 2);
+  clang_analyzer_eval(my_const_system_global > 2); // expected-warning {{TRUE}}
+  invalidate_globals();
+  clang_analyzer_eval(my_const_system_global > 2); // expected-warning {{TRUE}}
+}
+void test_my_const_system_global_assign(int);// One cannot assign value to a const lvalue.
+
+void test_my_mutable_system_global_constraint() {
+  assert(my_mutable_system_global > 2);
+  clang_analyzer_eval(my_mutable_system_global > 2); // expected-warning {{TRUE}}
+  invalidate_globals();
+  clang_analyzer_eval(my_mutable_system_global > 2); // expected-warning {{UNKNOWN}} It was previously TRUE.
+}
+void test_my_mutable_system_global_assign(int x) {
+  my_mutable_system_global = x;
+  clang_analyzer_eval(my_mutable_system_global == x); // expected-warning {{TRUE}}
+  invalidate_globals();
+  clang_analyzer_eval(my_mutable_system_global == x); // expected-warning {{UNKNOWN}} It was previously TRUE.
+}
Index: clang/test/Analysis/global-region-invalidation.c
===================================================================
--- clang/test/Analysis/global-region-invalidation.c
+++ clang/test/Analysis/global-region-invalidation.c
@@ -28,11 +28,17 @@
 void foo(void);
 int stdinTest(void) {
   int i = 0;
-  fscanf(stdin, "%d", &i);
+  fscanf(stdin, "%d", &i); // (1)
   foo();
   int m = i; // expected-warning + {{tainted}}
-  fscanf(stdin, "%d", &i);
-  int j = i; // expected-warning + {{tainted}}
+  fscanf(stdin, "%d", &i); // (2)
+
+  // The 'stdin' mutable system global variable gets invalidated by the first
+  // (1) opaque 'fscanf()' call. Consequently, the subsequent
+  // (2) 'fscanf(stdin, ...)' call won't propagate taint.
+  // FIXME: The analyzer engine should propagate taint by default on
+  // invalidation.
+  int j = i; // FIXME: should have 'tainted' warning here.
   return m + j; // expected-warning + {{tainted}}
 }
 
Index: clang/test/Analysis/Inputs/some_user_globals.h
===================================================================
--- /dev/null
+++ clang/test/Analysis/Inputs/some_user_globals.h
@@ -0,0 +1,2 @@
+extern const int my_const_user_global;
+extern int my_mutable_user_global;
Index: clang/test/Analysis/Inputs/some_system_globals.h
===================================================================
--- /dev/null
+++ clang/test/Analysis/Inputs/some_system_globals.h
@@ -0,0 +1,4 @@
+#pragma clang system_header
+
+extern const int my_const_system_global;
+extern int my_mutable_system_global;
Index: clang/lib/StaticAnalyzer/Core/MemRegion.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -973,26 +973,16 @@
   const MemRegion *sReg = nullptr;
 
   if (D->hasGlobalStorage() && !D->isStaticLocal()) {
-
-    // First handle the globals defined in system headers.
-    if (Ctx.getSourceManager().isInSystemHeader(D->getLocation())) {
-      //  Allow the system globals which often DO GET modified, assume the
-      // rest are immutable.
-      if (D->getName().contains("errno"))
-        sReg = getGlobalsRegion(MemRegion::GlobalSystemSpaceRegionKind);
-      else
-        sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind);
-
-    // Treat other globals as GlobalInternal unless they are constants.
-    } else {
-      QualType GQT = D->getType();
-      const Type *GT = GQT.getTypePtrOrNull();
+    QualType Ty = D->getType();
+    assert(!Ty.isNull());
+    if (Ty.isConstQualified() && Ty->isArithmeticType()) {
       // TODO: We could walk the complex types here and see if everything is
       // constified.
-      if (GT && GQT.isConstQualified() && GT->isArithmeticType())
-        sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind);
-      else
-        sReg = getGlobalsRegion();
+      sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind);
+    } else if (Ctx.getSourceManager().isInSystemHeader(D->getLocation())) {
+      sReg = getGlobalsRegion(MemRegion::GlobalSystemSpaceRegionKind);
+    } else {
+      sReg = getGlobalsRegion(MemRegion::GlobalInternalSpaceRegionKind);
     }
 
   // Finally handle static locals.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to