Print this page
11506 smatch resync

Split Close
Expand all
Collapse all
          --- old/usr/src/tools/smatch/src/smatch_function_hooks.c
          +++ new/usr/src/tools/smatch/src/smatch_function_hooks.c
↓ open down ↓ 131 lines elided ↑ open up ↑
 132  132  void return_implies_state(const char *look_for, long long start, long long end,
 133  133                           implication_hook *call_back, void *info)
 134  134  {
 135  135          struct fcall_back *cb;
 136  136  
 137  137          cb = alloc_fcall_back(RANGED_CALL, call_back, info);
 138  138          cb->range = alloc_range_perm(ll_to_sval(start), ll_to_sval(end));
 139  139          add_callback(func_hash, look_for, cb);
 140  140  }
 141  141  
      142 +void return_implies_state_sval(const char *look_for, sval_t start, sval_t end,
      143 +                         implication_hook *call_back, void *info)
      144 +{
      145 +        struct fcall_back *cb;
      146 +
      147 +        cb = alloc_fcall_back(RANGED_CALL, call_back, info);
      148 +        cb->range = alloc_range_perm(start, end);
      149 +        add_callback(func_hash, look_for, cb);
      150 +}
      151 +
 142  152  void select_return_states_hook(int type, return_implies_hook *callback)
 143  153  {
 144  154          struct return_implies_callback *cb = __alloc_return_implies_callback(0);
 145  155  
 146  156          cb->type = type;
 147  157          cb->callback = callback;
 148  158          add_ptr_list(&db_return_states_list, cb);
 149  159  }
 150  160  
 151  161  void select_return_states_before(void_fn *fn)
↓ open down ↓ 87 lines elided ↑ open up ↑
 239  249  {
 240  250          struct fcall_back *tmp;
 241  251          struct sm_state *sm;
 242  252          char *var_name;
 243  253          struct symbol *sym;
 244  254          struct smatch_state *estate;
 245  255          struct stree *tmp_stree;
 246  256          struct stree *final_states = NULL;
 247  257          struct range_list *handled_ranges = NULL;
 248  258          struct call_back_list *same_range_call_backs = NULL;
      259 +        struct range_list *rl;
 249  260          int handled = 0;
 250  261  
 251  262          if (!call_backs)
 252  263                  return 0;
 253  264  
 254  265          var_name = expr_to_var_sym(expr->left, &sym);
 255  266          if (!var_name || !sym)
 256  267                  goto free;
 257  268  
 258  269          FOR_EACH_PTR(call_backs, tmp) {
↓ open down ↓ 2 lines elided ↑ open up ↑
 261  272  
 262  273                  if (in_list_exact_sval(handled_ranges, tmp->range))
 263  274                          continue;
 264  275                  __push_fake_cur_stree();
 265  276                  tack_on(&handled_ranges, tmp->range);
 266  277  
 267  278                  same_range_call_backs = get_same_ranged_call_backs(call_backs, tmp->range);
 268  279                  call_ranged_call_backs(same_range_call_backs, fn, expr->right, expr);
 269  280                  __free_ptr_list((struct ptr_list **)&same_range_call_backs);
 270  281  
 271      -                estate = alloc_estate_range(tmp->range->min, tmp->range->max);
      282 +                rl = alloc_rl(tmp->range->min, tmp->range->max);
      283 +                rl = cast_rl(get_type(expr->left), rl);
      284 +                estate = alloc_estate_rl(rl);
 272  285                  set_extra_mod(var_name, sym, expr->left, estate);
 273  286  
 274  287                  tmp_stree = __pop_fake_cur_stree();
 275  288                  merge_fake_stree(&final_states, tmp_stree);
 276  289                  free_stree(&tmp_stree);
 277  290                  handled = 1;
 278  291          } END_FOR_EACH_PTR(tmp);
 279  292  
 280  293          FOR_EACH_SM(final_states, sm) {
 281  294                  __set_sm(sm);
↓ open down ↓ 73 lines elided ↑ open up ↑
 355  368  };
 356  369  
 357  370  static void store_return_state(struct db_callback_info *db_info, const char *ret_str, struct smatch_state *state)
 358  371  {
 359  372          db_info->ret_str = alloc_sname(ret_str),
 360  373          db_info->ret_state = state;
 361  374  }
 362  375  
 363  376  static bool fake_a_param_assignment(struct expression *expr, const char *return_str)
 364  377  {
 365      -        struct expression *arg, *left, *right, *fake_assign;
      378 +        struct expression *arg, *left, *right, *tmp, *fake_assign;
 366  379          char *p;
 367  380          int param;
 368  381          char buf[256];
 369  382          char *str;
 370  383  
 371  384          if (expr->type != EXPR_ASSIGNMENT || expr->op != '=')
 372  385                  return false;
 373  386          left = expr->left;
 374  387          right = expr->right;
 375  388  
↓ open down ↓ 19 lines elided ↑ open up ↑
 395  408          param = strtol(p, &p, 10);
 396  409  
 397  410          p = strchr(p, ']');
 398  411          if (!p || *p != ']')
 399  412                  return false;
 400  413          *p = '\0';
 401  414  
 402  415          arg = get_argument_from_call_expr(right->args, param);
 403  416          if (!arg)
 404  417                  return false;
      418 +
      419 +        /* There should be a get_other_name() function which returns an expr */
      420 +        tmp = get_assigned_expr(arg);
      421 +        if (tmp)
      422 +                arg = tmp;
      423 +
 405  424          /*
 406  425           * This is a sanity check to prevent side effects from evaluating stuff
 407  426           * twice.
 408  427           */
 409  428          str = expr_to_chunk_sym_vsl(arg, NULL, NULL);
 410  429          if (!str)
 411  430                  return false;
 412  431          free_string(str);
 413  432  
 414  433          right = gen_expression_from_key(arg, buf);
 415  434          if (!right)  /* Mostly fails for binops like [$0 + 4032] */
 416  435                  return false;
 417  436          fake_assign = assign_expression(left, '=', right);
 418  437          __in_fake_parameter_assign++;
 419  438          __split_expr(fake_assign);
 420  439          __in_fake_parameter_assign--;
 421  440          return true;
 422  441  }
 423  442  
 424      -static void set_return_state(struct expression *expr, struct db_callback_info *db_info)
      443 +static void set_return_assign_state(struct db_callback_info *db_info)
 425  444  {
      445 +        struct expression *expr = db_info->expr->left;
 426  446          struct smatch_state *state;
 427  447  
 428  448          if (!db_info->ret_state)
 429  449                  return;
 430  450  
 431  451          state = alloc_estate_rl(cast_rl(get_type(expr), clone_rl(estate_rl(db_info->ret_state))));
 432  452          set_extra_expr_mod(expr, state);
 433  453          db_info->ret_state = NULL;
 434  454          fake_a_param_assignment(db_info->expr, db_info->ret_str);
 435  455          db_info->ret_str = NULL;
 436  456  }
 437  457  
      458 +static void set_other_side_state(struct db_callback_info *db_info)
      459 +{
      460 +        struct expression *expr = db_info->var_expr;
      461 +        struct smatch_state *state;
      462 +
      463 +        if (!db_info->ret_state)
      464 +                return;
      465 +
      466 +        state = alloc_estate_rl(cast_rl(get_type(expr), clone_rl(estate_rl(db_info->ret_state))));
      467 +        set_extra_expr_nomod(expr, state);
      468 +        db_info->ret_state = NULL;
      469 +        db_info->ret_str = NULL;
      470 +}
      471 +
 438  472  static void handle_ret_equals_param(char *ret_string, struct range_list *rl, struct expression *call)
 439  473  {
 440  474          char *str;
 441  475          long long param;
 442  476          struct expression *arg;
 443  477          struct range_list *orig;
 444  478  
 445  479          str = strstr(ret_string, "==$");
 446  480          if (!str)
 447  481                  return;
↓ open down ↓ 106 lines elided ↑ open up ↑
 554  588  
 555  589          return 1;
 556  590  }
 557  591  
 558  592  static int db_compare_callback(void *_info, int argc, char **argv, char **azColName)
 559  593  {
 560  594          struct db_callback_info *db_info = _info;
 561  595          struct range_list *var_rl = db_info->rl;
 562  596          struct range_list *ret_range;
 563  597          int type, param;
 564      -        char *key, *value;
      598 +        char *ret_str, *key, *value;
 565  599          struct return_implies_callback *tmp;
 566  600          struct stree *stree;
 567  601          int return_id;
 568  602          int comparison;
 569  603  
 570  604          if (argc != 6)
 571  605                  return 0;
 572  606  
 573  607          return_id = atoi(argv[0]);
      608 +        ret_str = argv[1];
 574  609          type = atoi(argv[2]);
 575  610          param = atoi(argv[3]);
 576  611          key = argv[4];
 577  612          value = argv[5];
 578  613  
 579  614          db_info->has_states = 1;
 580  615          if (db_info->prev_return_id != -1 && type == INTERNAL) {
 581      -                set_return_state(db_info->var_expr, db_info);
      616 +                set_other_side_state(db_info);
 582  617                  stree = __pop_fake_cur_stree();
 583  618  
 584  619                  if (!db_info->cull)
 585  620                          merge_fake_stree(&db_info->stree, stree);
 586  621                  free_stree(&stree);
 587  622                  __push_fake_cur_stree();
 588  623                  db_info->cull = 0;
 589  624          }
 590  625          db_info->prev_return_id = return_id;
 591  626  
↓ open down ↓ 4 lines elided ↑ open up ↑
 596  631          if (type == CULL_PATH) {
 597  632                  db_info->cull = 1;
 598  633                  return 0;
 599  634          }
 600  635  
 601  636          if (is_impossible_data(type, db_info->expr, param, key, value)) {
 602  637                  db_info->cull = 1;
 603  638                  return 0;
 604  639          }
 605  640  
 606      -        call_results_to_rl(db_info->expr, get_type(strip_expr(db_info->expr)), argv[1], &ret_range);
      641 +        call_results_to_rl(db_info->expr, get_type(strip_expr(db_info->expr)), ret_str, &ret_range);
 607  642          ret_range = cast_rl(get_type(db_info->expr), ret_range);
 608  643          if (!ret_range)
 609  644                  ret_range = alloc_whole_rl(get_type(db_info->expr));
 610  645  
 611  646          comparison = db_info->comparison;
 612  647          if (db_info->left)
 613  648                  comparison = flip_comparison(comparison);
 614  649  
 615  650          if (db_info->true_side) {
 616  651                  if (!possibly_true_rl(var_rl, comparison, ret_range))
↓ open down ↓ 4 lines elided ↑ open up ↑
 621  656                  filter_by_comparison(&ret_range, flip_comparison(comparison), var_rl);
 622  657          } else {
 623  658                  if (!possibly_false_rl(var_rl, comparison, ret_range))
 624  659                          return 0;
 625  660                  if (type == PARAM_LIMIT)
 626  661                          param_limit_implications(db_info->expr, param, key, value);
 627  662                  filter_by_comparison(&var_rl, negate_comparison(comparison), ret_range);
 628  663                  filter_by_comparison(&ret_range, flip_comparison(negate_comparison(comparison)), var_rl);
 629  664          }
 630  665  
 631      -        handle_ret_equals_param(argv[1], ret_range, db_info->expr);
      666 +        handle_ret_equals_param(ret_str, ret_range, db_info->expr);
 632  667  
 633  668          if (type == INTERNAL) {
 634  669                  set_state(-1, "unnull_path", NULL, &true_state);
 635      -                __add_return_comparison(strip_expr(db_info->expr), argv[1]);
 636      -                __add_return_to_param_mapping(db_info->expr, argv[1]);
 637      -                store_return_state(db_info, argv[1], alloc_estate_rl(clone_rl(var_rl)));
      670 +                __add_return_comparison(strip_expr(db_info->expr), ret_str);
      671 +                __add_return_to_param_mapping(db_info->expr, ret_str);
      672 +                store_return_state(db_info, ret_str, alloc_estate_rl(clone_rl(var_rl)));
 638  673          }
 639  674  
 640  675          FOR_EACH_PTR(db_info->callbacks, tmp) {
 641  676                  if (tmp->type == type)
 642  677                          tmp->callback(db_info->expr, param, key, value);
 643  678          } END_FOR_EACH_PTR(tmp);
 644  679  
 645  680          return 0;
 646  681  }
 647  682  
↓ open down ↓ 32 lines elided ↑ open up ↑
 680  715          db_info.var_expr = var_expr;
 681  716  
 682  717          call_return_states_before_hooks();
 683  718  
 684  719          db_info.true_side = 1;
 685  720          db_info.stree = NULL;
 686  721          db_info.prev_return_id = -1;
 687  722          __push_fake_cur_stree();
 688  723          sql_select_return_states("return_id, return, type, parameter, key, value",
 689  724                                   call_expr, db_compare_callback, &db_info);
 690      -        set_return_state(db_info.var_expr, &db_info);
      725 +        set_other_side_state(&db_info);
 691  726          stree = __pop_fake_cur_stree();
 692      -        if (!db_info.cull) {
 693      -                set_return_state(db_info.var_expr, &db_info);
      727 +        if (!db_info.cull)
 694  728                  merge_fake_stree(&db_info.stree, stree);
 695      -        }
 696  729          free_stree(&stree);
 697  730          true_states = db_info.stree;
 698  731          if (!true_states && db_info.has_states) {
 699  732                  __push_fake_cur_stree();
 700  733                  set_path_impossible();
 701  734                  true_states = __pop_fake_cur_stree();
 702  735          }
 703  736  
 704  737          nullify_path();
 705  738          __unnullify_path();
↓ open down ↓ 1 lines elided ↑ open up ↑
 707  740                  __set_sm_cur_stree(sm);
 708  741          } END_FOR_EACH_SM(sm);
 709  742  
 710  743          db_info.true_side = 0;
 711  744          db_info.stree = NULL;
 712  745          db_info.prev_return_id = -1;
 713  746          db_info.cull = 0;
 714  747          __push_fake_cur_stree();
 715  748          sql_select_return_states("return_id, return, type, parameter, key, value", call_expr,
 716  749                          db_compare_callback, &db_info);
      750 +        set_other_side_state(&db_info);
 717  751          stree = __pop_fake_cur_stree();
 718      -        if (!db_info.cull) {
 719      -                set_return_state(db_info.var_expr, &db_info);
      752 +        if (!db_info.cull)
 720  753                  merge_fake_stree(&db_info.stree, stree);
 721      -        }
 722  754          free_stree(&stree);
 723  755          false_states = db_info.stree;
 724  756          if (!false_states && db_info.has_states) {
 725  757                  __push_fake_cur_stree();
 726  758                  set_path_impossible();
 727  759                  false_states = __pop_fake_cur_stree();
 728  760          }
 729  761  
 730  762          nullify_path();
 731  763          __unnullify_path();
↓ open down ↓ 67 lines elided ↑ open up ↑
 799  831          while (expr->type == EXPR_ASSIGNMENT)
 800  832                  expr = strip_expr(expr->right);
 801  833          if (expr->type != EXPR_CALL ||
 802  834              expr->fn->type != EXPR_SYMBOL)
 803  835                  return;
 804  836  
 805  837          fn = expr->fn->symbol_name->name;
 806  838  
 807  839          call_backs = search_callback(func_hash, fn);
 808  840          FOR_EACH_PTR(call_backs, tmp) {
 809      -                struct range_list *range_rl = NULL;
      841 +                struct range_list *range_rl;
 810  842  
 811  843                  if (tmp->type != RANGED_CALL)
 812  844                          continue;
 813      -                add_range(&range_rl, tmp->range->min, tmp->range->max);
      845 +                range_rl = alloc_rl(tmp->range->min, tmp->range->max);
 814  846                  range_rl = cast_rl(estate_type(db_info->ret_state), range_rl);
 815      -                if (possibly_true_rl(range_rl, SPECIAL_EQUAL, estate_rl(db_info->ret_state))) {
 816      -                        if (!possibly_true_rl(rl_invert(range_rl), SPECIAL_EQUAL, estate_rl(db_info->ret_state)))
 817      -                                (tmp->u.ranged)(fn, expr, db_info->expr, tmp->info);
 818      -                        else
 819      -                                db_info->handled = -1;
 820      -                }
      847 +                if (possibly_true_rl(range_rl, SPECIAL_EQUAL, estate_rl(db_info->ret_state)))
      848 +                        (tmp->u.ranged)(fn, expr, db_info->expr, tmp->info);
 821  849          } END_FOR_EACH_PTR(tmp);
 822  850  }
 823  851  
 824  852  static int db_assign_return_states_callback(void *_info, int argc, char **argv, char **azColName)
 825  853  {
 826  854          struct db_callback_info *db_info = _info;
 827  855          struct range_list *ret_range;
 828  856          int type, param;
 829      -        char *key, *value;
      857 +        char *ret_str, *key, *value;
 830  858          struct return_implies_callback *tmp;
 831  859          struct stree *stree;
 832  860          int return_id;
 833  861  
 834  862          if (argc != 6)
 835  863                  return 0;
 836  864  
 837  865          return_id = atoi(argv[0]);
      866 +        ret_str = argv[1];
 838  867          type = atoi(argv[2]);
 839  868          param = atoi(argv[3]);
 840  869          key = argv[4];
 841  870          value = argv[5];
 842  871  
 843  872          if (db_info->prev_return_id != -1 && type == INTERNAL) {
 844  873                  call_ranged_return_hooks(db_info);
 845      -                set_return_state(db_info->expr->left, db_info);
      874 +                set_return_assign_state(db_info);
 846  875                  stree = __pop_fake_cur_stree();
 847  876                  if (!db_info->cull)
 848  877                          merge_fake_stree(&db_info->stree, stree);
 849  878                  free_stree(&stree);
 850  879                  __push_fake_cur_stree();
 851  880                  db_info->cull = 0;
 852  881          }
 853  882          db_info->prev_return_id = return_id;
 854  883  
 855  884          if (type == INTERNAL && func_type_mismatch(db_info->expr, value))
↓ open down ↓ 6 lines elided ↑ open up ↑
 862  891          }
 863  892          if (is_impossible_data(type, db_info->expr, param, key, value)) {
 864  893                  db_info->cull = 1;
 865  894                  return 0;
 866  895          }
 867  896  
 868  897          if (type == PARAM_LIMIT)
 869  898                  param_limit_implications(db_info->expr, param, key, value);
 870  899  
 871  900          db_info->handled = 1;
 872      -        call_results_to_rl(db_info->expr->right, get_type(strip_expr(db_info->expr->right)), argv[1], &ret_range);
      901 +        call_results_to_rl(db_info->expr->right, get_type(strip_expr(db_info->expr->right)), ret_str, &ret_range);
 873  902          if (!ret_range)
 874  903                  ret_range = alloc_whole_rl(get_type(strip_expr(db_info->expr->right)));
 875  904          ret_range = cast_rl(get_type(db_info->expr->right), ret_range);
 876  905  
 877  906          if (type == INTERNAL) {
 878  907                  set_state(-1, "unnull_path", NULL, &true_state);
 879      -                __add_return_comparison(strip_expr(db_info->expr->right), argv[1]);
 880      -                __add_comparison_info(db_info->expr->left, strip_expr(db_info->expr->right), argv[1]);
 881      -                __add_return_to_param_mapping(db_info->expr, argv[1]);
 882      -                store_return_state(db_info, argv[1], alloc_estate_rl(ret_range));
      908 +                __add_return_comparison(strip_expr(db_info->expr->right), ret_str);
      909 +                __add_comparison_info(db_info->expr->left, strip_expr(db_info->expr->right), ret_str);
      910 +                __add_return_to_param_mapping(db_info->expr, ret_str);
      911 +                store_return_state(db_info, ret_str, alloc_estate_rl(ret_range));
 883  912          }
 884  913  
 885  914          FOR_EACH_PTR(db_return_states_list, tmp) {
 886  915                  if (tmp->type == type)
 887  916                          tmp->callback(db_info->expr, param, key, value);
 888  917          } END_FOR_EACH_PTR(tmp);
 889  918  
 890  919          return 0;
 891  920  }
 892  921  
↓ open down ↓ 17 lines elided ↑ open up ↑
 910  939          sql_select_return_states("return_id, return, type, parameter, key, value",
 911  940                          right, db_assign_return_states_callback, &db_info);
 912  941          if (option_debug) {
 913  942                  sm_msg("%s return_id %d return_ranges %s",
 914  943                          db_info.cull ? "culled" : "merging",
 915  944                          db_info.prev_return_id,
 916  945                          db_info.ret_state ? db_info.ret_state->name : "'<empty>'");
 917  946          }
 918  947          if (db_info.handled)
 919  948                  call_ranged_return_hooks(&db_info);
 920      -        set_return_state(db_info.expr->left, &db_info);
      949 +        set_return_assign_state(&db_info);
 921  950          stree = __pop_fake_cur_stree();
 922  951          if (!db_info.cull)
 923  952                  merge_fake_stree(&db_info.stree, stree);
 924  953          free_stree(&stree);
 925  954  
 926  955          if (!db_info.stree && db_info.cull) { /* this means we culled everything */
 927  956                  set_extra_expr_mod(expr->left, alloc_estate_whole(get_type(expr->left)));
 928  957                  set_path_impossible();
 929  958          }
 930  959          FOR_EACH_SM(db_info.stree, sm) {
↓ open down ↓ 73 lines elided ↑ open up ↑
1004 1033          get_absolute_rl(expr->right, &rl);
1005 1034          rl = cast_rl(get_type(expr->left), rl);
1006 1035          set_extra_expr_mod(expr->left, alloc_estate_rl(rl));
1007 1036  }
1008 1037  
1009 1038  static int db_return_states_callback(void *_info, int argc, char **argv, char **azColName)
1010 1039  {
1011 1040          struct db_callback_info *db_info = _info;
1012 1041          struct range_list *ret_range;
1013 1042          int type, param;
1014      -        char *key, *value;
     1043 +        char *ret_str, *key, *value;
1015 1044          struct return_implies_callback *tmp;
1016 1045          struct stree *stree;
1017 1046          int return_id;
1018 1047          char buf[64];
1019 1048  
1020 1049          if (argc != 6)
1021 1050                  return 0;
1022 1051  
1023 1052          return_id = atoi(argv[0]);
     1053 +        ret_str = argv[1];
1024 1054          type = atoi(argv[2]);
1025 1055          param = atoi(argv[3]);
1026 1056          key = argv[4];
1027 1057          value = argv[5];
1028 1058  
1029 1059          if (db_info->prev_return_id != -1 && type == INTERNAL) {
1030 1060                  stree = __pop_fake_cur_stree();
1031 1061                  if (!db_info->cull)
1032 1062                          merge_fake_stree(&db_info->stree, stree);
1033 1063                  free_stree(&stree);
↓ open down ↓ 12 lines elided ↑ open up ↑
1046 1076                  return 0;
1047 1077          }
1048 1078          if (is_impossible_data(type, db_info->expr, param, key, value)) {
1049 1079                  db_info->cull = 1;
1050 1080                  return 0;
1051 1081          }
1052 1082  
1053 1083          if (type == PARAM_LIMIT)
1054 1084                  param_limit_implications(db_info->expr, param, key, value);
1055 1085  
1056      -        call_results_to_rl(db_info->expr, get_type(strip_expr(db_info->expr)), argv[1], &ret_range);
     1086 +        call_results_to_rl(db_info->expr, get_type(strip_expr(db_info->expr)), ret_str, &ret_range);
1057 1087          ret_range = cast_rl(get_type(db_info->expr), ret_range);
1058 1088  
1059 1089          if (type == INTERNAL) {
1060 1090                  set_state(-1, "unnull_path", NULL, &true_state);
1061      -                __add_return_comparison(strip_expr(db_info->expr), argv[1]);
1062      -                __add_return_to_param_mapping(db_info->expr, argv[1]);
     1091 +                __add_return_comparison(strip_expr(db_info->expr), ret_str);
     1092 +                __add_return_to_param_mapping(db_info->expr, ret_str);
1063 1093          }
1064 1094  
1065 1095  
1066 1096          FOR_EACH_PTR(db_return_states_list, tmp) {
1067 1097                  if (tmp->type == type)
1068 1098                          tmp->callback(db_info->expr, param, key, value);
1069 1099          } END_FOR_EACH_PTR(tmp);
1070 1100  
1071 1101          /*
1072 1102           * We want to store the return values so that we can split the strees
↓ open down ↓ 134 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX