Print this page
11972 resync smatch


  27  *
  28  * So the smatch_flow.c understands code but it doesn't understand states.
  29  * smatch_flow calls functions in this file.  This file calls functions
  30  * in smatch_slist.c which just has boring generic plumbing for handling
  31  * state lists.  But really it's this file where all the magic happens.
  32  */
  33 
  34 #include <stdlib.h>
  35 #include <stdio.h>
  36 #include "smatch.h"
  37 #include "smatch_slist.h"
  38 #include "smatch_extra.h"
  39 
  40 struct smatch_state undefined = { .name = "undefined" };
  41 struct smatch_state ghost = { .name = "ghost" };
  42 struct smatch_state merged = { .name = "merged" };
  43 struct smatch_state true_state = { .name = "true" };
  44 struct smatch_state false_state = { .name = "false" };
  45 
  46 static struct stree *cur_stree; /* current states */

  47 
  48 static struct stree_stack *true_stack; /* states after a t/f branch */
  49 static struct stree_stack *false_stack;
  50 static struct stree_stack *pre_cond_stack; /* states before a t/f branch */
  51 
  52 static struct stree_stack *cond_true_stack; /* states affected by a branch */
  53 static struct stree_stack *cond_false_stack;
  54 
  55 static struct stree_stack *fake_cur_stree_stack;
  56 static int read_only;
  57 
  58 static struct stree_stack *break_stack;
  59 static struct stree_stack *fake_break_stack;
  60 static struct stree_stack *switch_stack;
  61 static struct range_list_stack *remaining_cases;
  62 static struct stree_stack *default_stack;
  63 static struct stree_stack *continue_stack;
  64 
  65 static struct named_stree_stack *goto_stack;
  66 
  67 static struct ptr_list *backup;
  68 
  69 int option_debug;
  70 
  71 void __print_cur_stree(void)
  72 {
  73         __print_stree(cur_stree);
  74 }
  75 
  76 int unreachable(void)
  77 {
  78         if (!cur_stree)
  79                 return 1;
  80         return 0;
  81 }
  82 










  83 struct sm_state *set_state(int owner, const char *name, struct symbol *sym, struct smatch_state *state)
  84 {
  85         struct sm_state *ret;
  86 
  87         if (!name || !state)
  88                 return NULL;
  89 
  90         if (read_only)
  91                 sm_perror("cur_stree is read only.");
  92 
  93         if (option_debug || strcmp(check_name(owner), option_debug_check) == 0) {
  94                 struct smatch_state *s;
  95 
  96                 s = __get_state(owner, name, sym);
  97                 if (!s)
  98                         sm_msg("%s new [%s] '%s' %s", __func__,
  99                                check_name(owner), name, show_state(state));
 100                 else
 101                         sm_msg("%s change [%s] '%s' %s => %s",
 102                                 __func__, check_name(owner), name, show_state(s),


 113 
 114         return ret;
 115 }
 116 
 117 struct sm_state *set_state_expr(int owner, struct expression *expr, struct smatch_state *state)
 118 {
 119         char *name;
 120         struct symbol *sym;
 121         struct sm_state *ret = NULL;
 122 
 123         expr = strip_expr(expr);
 124         name = expr_to_var_sym(expr, &sym);
 125         if (!name || !sym)
 126                 goto free;
 127         ret = set_state(owner, name, sym, state);
 128 free:
 129         free_string(name);
 130         return ret;
 131 }
 132 
 133 void __swap_cur_stree(struct stree *stree)
 134 {
 135         free_stree(&cur_stree);

 136         cur_stree = stree;

 137 }
 138 
 139 void __push_fake_cur_stree(void)
 140 {
 141         push_stree(&fake_cur_stree_stack, NULL);
 142         __save_pre_cond_states();
 143 }
 144 
 145 struct stree *__pop_fake_cur_stree(void)
 146 {
 147         if (!fake_cur_stree_stack)
 148                 sm_perror("popping too many fake cur strees.");
 149         __use_pre_cond_states();
 150         return pop_stree(&fake_cur_stree_stack);
 151 }
 152 
 153 void __free_fake_cur_stree(void)
 154 {
 155         struct stree *stree;
 156 
 157         stree = __pop_fake_cur_stree();
 158         free_stree(&stree);
 159 }
 160 
 161 void __set_fake_cur_stree_fast(struct stree *stree)
 162 {
 163         push_stree(&pre_cond_stack, cur_stree);
 164         cur_stree = stree;
 165         read_only = 1;



 166 }
 167 
 168 void __pop_fake_cur_stree_fast(void)
 169 {
 170         cur_stree = pop_stree(&pre_cond_stack);
 171         read_only = 0;
 172 }
 173 
 174 void __merge_stree_into_cur(struct stree *stree)
 175 {
 176         struct sm_state *sm;
 177         struct sm_state *orig;
 178         struct sm_state *merged;
 179 
 180         FOR_EACH_SM(stree, sm) {
 181                 orig = get_sm_state(sm->owner, sm->name, sm->sym);
 182                 if (orig)
 183                         merged = merge_sm_states(orig, sm);
 184                 else
 185                         merged = sm;
 186                 __set_sm(merged);
 187         } END_FOR_EACH_SM(sm);
 188 }
 189 
 190 void __set_sm(struct sm_state *sm)
 191 {


 272 }
 273 
 274 static void call_get_state_hooks(int owner, const char *name, struct symbol *sym)
 275 {
 276         static int recursion;
 277         get_state_hook **fn;
 278 
 279         if (recursion)
 280                 return;
 281         recursion = 1;
 282 
 283         FOR_EACH_PTR(get_state_hooks, fn) {
 284                 (*fn)(owner, name, sym);
 285         } END_FOR_EACH_PTR(fn);
 286 
 287         recursion = 0;
 288 }
 289 
 290 struct smatch_state *__get_state(int owner, const char *name, struct symbol *sym)
 291 {
 292         return get_state_stree(cur_stree, owner, name, sym);





 293 }
 294 
 295 struct smatch_state *get_state(int owner, const char *name, struct symbol *sym)
 296 {
 297         call_get_state_hooks(owner, name, sym);
 298 
 299         return __get_state(owner, name, sym);
 300 }
 301 
 302 struct smatch_state *get_state_expr(int owner, struct expression *expr)
 303 {
 304         char *name;
 305         struct symbol *sym;
 306         struct smatch_state *ret = NULL;
 307 
 308         expr = strip_expr(expr);
 309         name = expr_to_var_sym(expr, &sym);
 310         if (!name || !sym)
 311                 goto free;
 312         ret = get_state(owner, name, sym);


 326 }
 327 
 328 struct state_list *get_possible_states_expr(int owner, struct expression *expr)
 329 {
 330         char *name;
 331         struct symbol *sym;
 332         struct state_list *ret = NULL;
 333 
 334         expr = strip_expr(expr);
 335         name = expr_to_var_sym(expr, &sym);
 336         if (!name || !sym)
 337                 goto free;
 338         ret = get_possible_states(owner, name, sym);
 339 free:
 340         free_string(name);
 341         return ret;
 342 }
 343 
 344 struct sm_state *get_sm_state(int owner, const char *name, struct symbol *sym)
 345 {






 346         return get_sm_state_stree(cur_stree, owner, name, sym);
 347 }
 348 
 349 struct sm_state *get_sm_state_expr(int owner, struct expression *expr)
 350 {
 351         char *name;
 352         struct symbol *sym;
 353         struct sm_state *ret = NULL;
 354 
 355         expr = strip_expr(expr);
 356         name = expr_to_var_sym(expr, &sym);
 357         if (!name || !sym)
 358                 goto free;
 359         ret = get_sm_state(owner, name, sym);
 360 free:
 361         free_string(name);
 362         return ret;
 363 }
 364 
 365 void delete_state(int owner, const char *name, struct symbol *sym)


 576                 set_state(-1, "unnull_path", NULL, &true_state);
 577 }
 578 
 579 int __path_is_null(void)
 580 {
 581         if (cur_stree)
 582                 return 0;
 583         return 1;
 584 }
 585 
 586 static void check_stree_stack_free(struct stree_stack **stack)
 587 {
 588         if (*stack) {
 589                 sm_perror("stack not empty");
 590                 free_stack_and_strees(stack);
 591         }
 592 }
 593 
 594 void save_all_states(void)
 595 {
 596         __add_ptr_list(&backup, cur_stree, 0);
 597         cur_stree = NULL;
 598 
 599         __add_ptr_list(&backup, true_stack, 0);
 600         true_stack = NULL;
 601         __add_ptr_list(&backup, false_stack, 0);
 602         false_stack = NULL;
 603         __add_ptr_list(&backup, pre_cond_stack, 0);
 604         pre_cond_stack = NULL;
 605 
 606         __add_ptr_list(&backup, cond_true_stack, 0);
 607         cond_true_stack = NULL;
 608         __add_ptr_list(&backup, cond_false_stack, 0);
 609         cond_false_stack = NULL;
 610 
 611         __add_ptr_list(&backup, fake_cur_stree_stack, 0);
 612         fake_cur_stree_stack = NULL;
 613 
 614         __add_ptr_list(&backup, break_stack, 0);
 615         break_stack = NULL;
 616         __add_ptr_list(&backup, fake_break_stack, 0);
 617         fake_break_stack = NULL;
 618 
 619         __add_ptr_list(&backup, switch_stack, 0);
 620         switch_stack = NULL;
 621         __add_ptr_list(&backup, remaining_cases, 0);
 622         remaining_cases = NULL;
 623         __add_ptr_list(&backup, default_stack, 0);
 624         default_stack = NULL;
 625         __add_ptr_list(&backup, continue_stack, 0);
 626         continue_stack = NULL;
 627 
 628         __add_ptr_list(&backup, goto_stack, 0);
 629         goto_stack = NULL;
 630 }
 631 
 632 static void *pop_backup(void)
 633 {
 634         void *ret;
 635 
 636         ret = last_ptr_list(backup);
 637         delete_ptr_list_last(&backup);
 638         return ret;
 639 }
 640 
 641 void restore_all_states(void)
 642 {
 643         goto_stack = pop_backup();
 644 
 645         continue_stack = pop_backup();
 646         default_stack = pop_backup();
 647         remaining_cases = pop_backup();
 648         switch_stack = pop_backup();




  27  *
  28  * So the smatch_flow.c understands code but it doesn't understand states.
  29  * smatch_flow calls functions in this file.  This file calls functions
  30  * in smatch_slist.c which just has boring generic plumbing for handling
  31  * state lists.  But really it's this file where all the magic happens.
  32  */
  33 
  34 #include <stdlib.h>
  35 #include <stdio.h>
  36 #include "smatch.h"
  37 #include "smatch_slist.h"
  38 #include "smatch_extra.h"
  39 
  40 struct smatch_state undefined = { .name = "undefined" };
  41 struct smatch_state ghost = { .name = "ghost" };
  42 struct smatch_state merged = { .name = "merged" };
  43 struct smatch_state true_state = { .name = "true" };
  44 struct smatch_state false_state = { .name = "false" };
  45 
  46 static struct stree *cur_stree; /* current states */
  47 static struct stree *fast_overlay;
  48 
  49 static struct stree_stack *true_stack; /* states after a t/f branch */
  50 static struct stree_stack *false_stack;
  51 static struct stree_stack *pre_cond_stack; /* states before a t/f branch */
  52 
  53 static struct stree_stack *cond_true_stack; /* states affected by a branch */
  54 static struct stree_stack *cond_false_stack;
  55 
  56 static struct stree_stack *fake_cur_stree_stack;
  57 static int read_only;
  58 
  59 static struct stree_stack *break_stack;
  60 static struct stree_stack *fake_break_stack;
  61 static struct stree_stack *switch_stack;
  62 static struct range_list_stack *remaining_cases;
  63 static struct stree_stack *default_stack;
  64 static struct stree_stack *continue_stack;
  65 
  66 static struct named_stree_stack *goto_stack;
  67 
  68 static struct ptr_list *backup;
  69 
  70 int option_debug;
  71 
  72 void __print_cur_stree(void)
  73 {
  74         __print_stree(cur_stree);
  75 }
  76 
  77 int unreachable(void)
  78 {
  79         if (!cur_stree)
  80                 return 1;
  81         return 0;
  82 }
  83 
  84 void __set_cur_stree_readonly(void)
  85 {
  86         read_only++;
  87 }
  88 
  89 void __set_cur_stree_writable(void)
  90 {
  91         read_only--;
  92 }
  93 
  94 struct sm_state *set_state(int owner, const char *name, struct symbol *sym, struct smatch_state *state)
  95 {
  96         struct sm_state *ret;
  97 
  98         if (!name || !state)
  99                 return NULL;
 100 
 101         if (read_only)
 102                 sm_perror("cur_stree is read only.");
 103 
 104         if (option_debug || strcmp(check_name(owner), option_debug_check) == 0) {
 105                 struct smatch_state *s;
 106 
 107                 s = __get_state(owner, name, sym);
 108                 if (!s)
 109                         sm_msg("%s new [%s] '%s' %s", __func__,
 110                                check_name(owner), name, show_state(state));
 111                 else
 112                         sm_msg("%s change [%s] '%s' %s => %s",
 113                                 __func__, check_name(owner), name, show_state(s),


 124 
 125         return ret;
 126 }
 127 
 128 struct sm_state *set_state_expr(int owner, struct expression *expr, struct smatch_state *state)
 129 {
 130         char *name;
 131         struct symbol *sym;
 132         struct sm_state *ret = NULL;
 133 
 134         expr = strip_expr(expr);
 135         name = expr_to_var_sym(expr, &sym);
 136         if (!name || !sym)
 137                 goto free;
 138         ret = set_state(owner, name, sym, state);
 139 free:
 140         free_string(name);
 141         return ret;
 142 }
 143 
 144 struct stree *__swap_cur_stree(struct stree *stree)
 145 {
 146         struct stree *orig = cur_stree;
 147 
 148         cur_stree = stree;
 149         return orig;
 150 }
 151 
 152 void __push_fake_cur_stree(void)
 153 {
 154         push_stree(&fake_cur_stree_stack, NULL);
 155         __save_pre_cond_states();
 156 }
 157 
 158 struct stree *__pop_fake_cur_stree(void)
 159 {
 160         if (!fake_cur_stree_stack)
 161                 sm_perror("popping too many fake cur strees.");
 162         __use_pre_cond_states();
 163         return pop_stree(&fake_cur_stree_stack);
 164 }
 165 
 166 void __free_fake_cur_stree(void)
 167 {
 168         struct stree *stree;
 169 
 170         stree = __pop_fake_cur_stree();
 171         free_stree(&stree);
 172 }
 173 
 174 void __set_fake_cur_stree_fast(struct stree *stree)
 175 {
 176         if (fast_overlay) {
 177                 sm_perror("cannot nest fast overlay");
 178                 return;
 179         }
 180         fast_overlay = stree;
 181         set_fast_math_only();
 182 }
 183 
 184 void __pop_fake_cur_stree_fast(void)
 185 {
 186         fast_overlay = NULL;
 187         clear_fast_math_only();
 188 }
 189 
 190 void __merge_stree_into_cur(struct stree *stree)
 191 {
 192         struct sm_state *sm;
 193         struct sm_state *orig;
 194         struct sm_state *merged;
 195 
 196         FOR_EACH_SM(stree, sm) {
 197                 orig = get_sm_state(sm->owner, sm->name, sm->sym);
 198                 if (orig)
 199                         merged = merge_sm_states(orig, sm);
 200                 else
 201                         merged = sm;
 202                 __set_sm(merged);
 203         } END_FOR_EACH_SM(sm);
 204 }
 205 
 206 void __set_sm(struct sm_state *sm)
 207 {


 288 }
 289 
 290 static void call_get_state_hooks(int owner, const char *name, struct symbol *sym)
 291 {
 292         static int recursion;
 293         get_state_hook **fn;
 294 
 295         if (recursion)
 296                 return;
 297         recursion = 1;
 298 
 299         FOR_EACH_PTR(get_state_hooks, fn) {
 300                 (*fn)(owner, name, sym);
 301         } END_FOR_EACH_PTR(fn);
 302 
 303         recursion = 0;
 304 }
 305 
 306 struct smatch_state *__get_state(int owner, const char *name, struct symbol *sym)
 307 {
 308         struct sm_state *sm;
 309 
 310         sm = get_sm_state(owner, name, sym);
 311         if (!sm)
 312                 return NULL;
 313         return sm->state;
 314 }
 315 
 316 struct smatch_state *get_state(int owner, const char *name, struct symbol *sym)
 317 {
 318         call_get_state_hooks(owner, name, sym);
 319 
 320         return __get_state(owner, name, sym);
 321 }
 322 
 323 struct smatch_state *get_state_expr(int owner, struct expression *expr)
 324 {
 325         char *name;
 326         struct symbol *sym;
 327         struct smatch_state *ret = NULL;
 328 
 329         expr = strip_expr(expr);
 330         name = expr_to_var_sym(expr, &sym);
 331         if (!name || !sym)
 332                 goto free;
 333         ret = get_state(owner, name, sym);


 347 }
 348 
 349 struct state_list *get_possible_states_expr(int owner, struct expression *expr)
 350 {
 351         char *name;
 352         struct symbol *sym;
 353         struct state_list *ret = NULL;
 354 
 355         expr = strip_expr(expr);
 356         name = expr_to_var_sym(expr, &sym);
 357         if (!name || !sym)
 358                 goto free;
 359         ret = get_possible_states(owner, name, sym);
 360 free:
 361         free_string(name);
 362         return ret;
 363 }
 364 
 365 struct sm_state *get_sm_state(int owner, const char *name, struct symbol *sym)
 366 {
 367         struct sm_state *ret;
 368 
 369         ret = get_sm_state_stree(fast_overlay, owner, name, sym);
 370         if (ret)
 371                 return ret;
 372 
 373         return get_sm_state_stree(cur_stree, owner, name, sym);
 374 }
 375 
 376 struct sm_state *get_sm_state_expr(int owner, struct expression *expr)
 377 {
 378         char *name;
 379         struct symbol *sym;
 380         struct sm_state *ret = NULL;
 381 
 382         expr = strip_expr(expr);
 383         name = expr_to_var_sym(expr, &sym);
 384         if (!name || !sym)
 385                 goto free;
 386         ret = get_sm_state(owner, name, sym);
 387 free:
 388         free_string(name);
 389         return ret;
 390 }
 391 
 392 void delete_state(int owner, const char *name, struct symbol *sym)


 603                 set_state(-1, "unnull_path", NULL, &true_state);
 604 }
 605 
 606 int __path_is_null(void)
 607 {
 608         if (cur_stree)
 609                 return 0;
 610         return 1;
 611 }
 612 
 613 static void check_stree_stack_free(struct stree_stack **stack)
 614 {
 615         if (*stack) {
 616                 sm_perror("stack not empty");
 617                 free_stack_and_strees(stack);
 618         }
 619 }
 620 
 621 void save_all_states(void)
 622 {
 623         __add_ptr_list(&backup, cur_stree);
 624         cur_stree = NULL;
 625 
 626         __add_ptr_list(&backup, true_stack);
 627         true_stack = NULL;
 628         __add_ptr_list(&backup, false_stack);
 629         false_stack = NULL;
 630         __add_ptr_list(&backup, pre_cond_stack);
 631         pre_cond_stack = NULL;
 632 
 633         __add_ptr_list(&backup, cond_true_stack);
 634         cond_true_stack = NULL;
 635         __add_ptr_list(&backup, cond_false_stack);
 636         cond_false_stack = NULL;
 637 
 638         __add_ptr_list(&backup, fake_cur_stree_stack);
 639         fake_cur_stree_stack = NULL;
 640 
 641         __add_ptr_list(&backup, break_stack);
 642         break_stack = NULL;
 643         __add_ptr_list(&backup, fake_break_stack);
 644         fake_break_stack = NULL;
 645 
 646         __add_ptr_list(&backup, switch_stack);
 647         switch_stack = NULL;
 648         __add_ptr_list(&backup, remaining_cases);
 649         remaining_cases = NULL;
 650         __add_ptr_list(&backup, default_stack);
 651         default_stack = NULL;
 652         __add_ptr_list(&backup, continue_stack);
 653         continue_stack = NULL;
 654 
 655         __add_ptr_list(&backup, goto_stack);
 656         goto_stack = NULL;
 657 }
 658 
 659 static void *pop_backup(void)
 660 {
 661         void *ret;
 662 
 663         ret = last_ptr_list(backup);
 664         delete_ptr_list_last(&backup);
 665         return ret;
 666 }
 667 
 668 void restore_all_states(void)
 669 {
 670         goto_stack = pop_backup();
 671 
 672         continue_stack = pop_backup();
 673         default_stack = pop_backup();
 674         remaining_cases = pop_backup();
 675         switch_stack = pop_backup();