Home | History | Annotate | Download | only in Analysis
      1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-max-loop 4 -analyzer-config widen-loops=true -verify %s
      2 
      3 void clang_analyzer_eval(int);
      4 void clang_analyzer_warnIfReached();
      5 
      6 typedef __typeof(sizeof(int)) size_t;
      7 void *malloc(size_t);
      8 void free(void *);
      9 
     10 void loop_which_iterates_limit_times_not_widened() {
     11   int i;
     12   int x = 1;
     13   // Check loop isn't widened by checking x isn't invalidated
     14   for (i = 0; i < 1; ++i) {}
     15   clang_analyzer_eval(x == 1); // expected-warning {{TRUE}}
     16   for (i = 0; i < 2; ++i) {}
     17   clang_analyzer_eval(x == 1); // expected-warning {{TRUE}}
     18   for (i = 0; i < 3; ++i) {}
     19   // FIXME loss of precision as a result of evaluating the widened loop body
     20   //       *instead* of the last iteration.
     21   clang_analyzer_eval(x == 1); // expected-warning {{UNKNOWN}}
     22 }
     23 
     24 int a_global;
     25 
     26 void loop_evaluated_before_widening() {
     27   int i;
     28   a_global = 1;
     29   for (i = 0; i < 10; ++i) {
     30     if (i == 2) {
     31       // True before widening then unknown after.
     32       clang_analyzer_eval(a_global == 1); // expected-warning{{TRUE}} expected-warning{{UNKNOWN}}
     33     }
     34   }
     35   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
     36 }
     37 
     38 void warnings_after_loop() {
     39   int i;
     40   for (i = 0; i < 10; ++i) {}
     41   char *m = (char*)malloc(12);
     42 } // expected-warning {{Potential leak of memory pointed to by 'm'}}
     43 
     44 void for_loop_exits() {
     45   int i;
     46   for (i = 0; i < 10; ++i) {}
     47   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
     48 }
     49 
     50 void while_loop_exits() {
     51   int i = 0;
     52   while (i < 10) {++i;}
     53   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
     54 }
     55 
     56 void do_while_loop_exits() {
     57   int i = 0;
     58   do {++i;} while (i < 10);
     59   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
     60 }
     61 
     62 void loop_body_is_widened() {
     63   int i = 0;
     64   while (i < 100) {
     65     if (i > 10) {
     66       clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
     67     }
     68     ++i;
     69   }
     70   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
     71 }
     72 
     73 void invariably_infinite_loop() {
     74   int i = 0;
     75   while (1) { ++i; }
     76   clang_analyzer_warnIfReached(); // no-warning
     77 }
     78 
     79 void invariably_infinite_break_loop() {
     80   int i = 0;
     81   while (1) {
     82     ++i;
     83     int x = 1;
     84     if (!x) break;
     85   }
     86   clang_analyzer_warnIfReached(); // no-warning
     87 }
     88 
     89 void reachable_break_loop() {
     90   int i = 0;
     91   while (1) {
     92     ++i;
     93     if (i == 100) break;
     94   }
     95   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
     96 }
     97 
     98 void condition_constrained_true_in_loop() {
     99   int i = 0;
    100   while (i < 50) {
    101     clang_analyzer_eval(i < 50); // expected-warning {{TRUE}}
    102     ++i;
    103   }
    104   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
    105 }
    106 
    107 void condition_constrained_false_after_loop() {
    108   int i = 0;
    109   while (i < 50) {
    110     ++i;
    111   }
    112   clang_analyzer_eval(i >= 50); // expected-warning {{TRUE}}
    113   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
    114 }
    115 
    116 void multiple_exit_test() {
    117   int x = 0;
    118   int i = 0;
    119   while (i < 50) {
    120     if (x) {
    121       i = 10;
    122       break;
    123     }
    124     ++i;
    125   }
    126   // Reachable by 'normal' exit
    127   if (i == 50) clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
    128   // Reachable by break point
    129   if (i == 10) clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
    130   // Not reachable
    131   if (i < 10) clang_analyzer_warnIfReached(); // no-warning
    132   if (i > 10 && i < 50) clang_analyzer_warnIfReached(); // no-warning
    133 }
    134 
    135 void pointer_doesnt_leak_from_loop() {
    136   int *h_ptr = (int *) malloc(sizeof(int));
    137   for (int i = 0; i < 2; ++i) {}
    138   for (int i = 0; i < 10; ++i) {} // no-warning
    139   free(h_ptr);
    140 }
    141 
    142 int g_global;
    143 
    144 void unknown_after_loop(int s_arg) {
    145   g_global = 0;
    146   s_arg = 1;
    147   int s_local = 2;
    148   int *h_ptr = malloc(sizeof(int));
    149 
    150   for (int i = 0; i < 10; ++i) {}
    151 
    152   clang_analyzer_eval(g_global); // expected-warning {{UNKNOWN}}
    153   clang_analyzer_eval(s_arg); // expected-warning {{UNKNOWN}}
    154   clang_analyzer_eval(s_local); // expected-warning {{UNKNOWN}}
    155   clang_analyzer_eval(h_ptr == 0); // expected-warning {{UNKNOWN}}
    156   free(h_ptr);
    157 }
    158 
    159 void variable_bound_exiting_loops_widened(int x) {
    160   int i = 0;
    161   int t = 1;
    162   while (i < x) {
    163     ++i;
    164   }
    165   clang_analyzer_eval(t == 1); // expected-warning {{TRUE}} // expected-warning {{UNKNOWN}}
    166 }
    167 
    168 void nested_loop_outer_widen() {
    169   int i = 0, j = 0;
    170   for (i = 0; i < 10; i++) {
    171     clang_analyzer_eval(i < 10); // expected-warning {{TRUE}}
    172     for (j = 0; j < 2; j++) {
    173       clang_analyzer_eval(j < 2); // expected-warning {{TRUE}}
    174     }
    175     clang_analyzer_eval(j >= 2); // expected-warning {{TRUE}}
    176   }
    177   clang_analyzer_eval(i >= 10); // expected-warning {{TRUE}}
    178 }
    179 
    180 void nested_loop_inner_widen() {
    181   int i = 0, j = 0;
    182   for (i = 0; i < 2; i++) {
    183     clang_analyzer_eval(i < 2); // expected-warning {{TRUE}}
    184     for (j = 0; j < 10; j++) {
    185       clang_analyzer_eval(j < 10); // expected-warning {{TRUE}}
    186     }
    187     clang_analyzer_eval(j >= 10); // expected-warning {{TRUE}}
    188   }
    189   clang_analyzer_eval(i >= 2); // expected-warning {{TRUE}}
    190 }
    191