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