Home | History | Annotate | Download | only in Analysis
      1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
      2 // RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
      3 // XFAIL: *
      4 
      5 // This file is for tests that may eventually go into string.c, or may be
      6 // deleted outright. At one point these tests passed, but only because we
      7 // weren't correctly modelling the behavior of the relevant string functions.
      8 // The tests aren't incorrect, but require the analyzer to be smarter about
      9 // conjured values than it currently is.
     10 
     11 //===----------------------------------------------------------------------===
     12 // Declarations
     13 //===----------------------------------------------------------------------===
     14 
     15 // Some functions are so similar to each other that they follow the same code
     16 // path, such as memcpy and __memcpy_chk, or memcmp and bcmp. If VARIANT is
     17 // defined, make sure to use the variants instead to make sure they are still
     18 // checked by the analyzer.
     19 
     20 // Some functions are implemented as builtins. These should be #defined as
     21 // BUILTIN(f), which will prepend "__builtin_" if USE_BUILTINS is defined.
     22 
     23 // Functions that have variants and are also available as builtins should be
     24 // declared carefully! See memcpy() for an example.
     25 
     26 #ifdef USE_BUILTINS
     27 # define BUILTIN(f) __builtin_ ## f
     28 #else /* USE_BUILTINS */
     29 # define BUILTIN(f) f
     30 #endif /* USE_BUILTINS */
     31 
     32 #define NULL 0
     33 typedef typeof(sizeof(int)) size_t;
     34 
     35 void clang_analyzer_eval(int);
     36 
     37 //===----------------------------------------------------------------------===
     38 // strnlen()
     39 //===----------------------------------------------------------------------===
     40 
     41 #define strnlen BUILTIN(strnlen)
     42 size_t strnlen(const char *s, size_t maxlen);
     43 
     44 void strnlen_liveness(const char *x) {
     45   if (strnlen(x, 10) < 5)
     46     return;
     47   clang_analyzer_eval(strnlen(x, 10) < 5); // expected-warning{{FALSE}}
     48 }
     49 
     50 void strnlen_subregion() {
     51   struct two_stringsn { char a[2], b[2]; };
     52   extern void use_two_stringsn(struct two_stringsn *);
     53 
     54   struct two_stringsn z;
     55   use_two_stringsn(&z);
     56 
     57   size_t a = strnlen(z.a, 10);
     58   z.b[0] = 5;
     59   size_t b = strnlen(z.a, 10);
     60   if (a == 0)
     61     clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
     62 
     63   use_two_stringsn(&z);
     64 
     65   size_t c = strnlen(z.a, 10);
     66   if (a == 0)
     67     clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
     68 }
     69 
     70 extern void use_stringn(char *);
     71 void strnlen_argument(char *x) {
     72   size_t a = strnlen(x, 10);
     73   size_t b = strnlen(x, 10);
     74   if (a == 0)
     75     clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
     76 
     77   use_stringn(x);
     78 
     79   size_t c = strnlen(x, 10);
     80   if (a == 0)
     81     clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
     82 }
     83 
     84 extern char global_strn[];
     85 void strnlen_global() {
     86   size_t a = strnlen(global_strn, 10);
     87   size_t b = strnlen(global_strn, 10);
     88   if (a == 0)
     89     clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
     90 
     91   // Call a function with unknown effects, which should invalidate globals.
     92   use_stringn(0);
     93 
     94   size_t c = strnlen(global_strn, 10);
     95   if (a == 0)
     96     clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
     97 }
     98 
     99 void strnlen_indirect(char *x) {
    100   size_t a = strnlen(x, 10);
    101   char *p = x;
    102   char **p2 = &p;
    103   size_t b = strnlen(x, 10);
    104   if (a == 0)
    105     clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
    106 
    107   extern void use_stringn_ptr(char*const*);
    108   use_stringn_ptr(p2);
    109 
    110   size_t c = strnlen(x, 10);
    111   if (a == 0)
    112     clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
    113 }
    114