Print this page
11506 smatch resync

Split Close
Expand all
Collapse all
          --- old/usr/src/tools/smatch/src/smatch_comparison.c
          +++ new/usr/src/tools/smatch/src/smatch_comparison.c
↓ open down ↓ 633 lines elided ↑ open up ↑
 634  634          else
 635  635                  links = NULL;
 636  636  
 637  637          new = alloc_sname(link);
 638  638          insert_string(&links, new);
 639  639  
 640  640          new_state = alloc_link_state(links);
 641  641          set_state(link_id, var, sym, new_state);
 642  642  }
 643  643  
 644      -static void match_inc(struct sm_state *sm)
      644 +static void match_inc(struct sm_state *sm, bool preserve)
 645  645  {
 646  646          struct string_list *links;
 647  647          struct smatch_state *state, *new;
 648  648          struct compare_data *data;
 649  649          char *tmp;
 650  650          int flip;
 651  651          int op;
 652  652  
 653  653          links = sm->state->data;
 654  654  
↓ open down ↓ 11 lines elided ↑ open up ↑
 666  666                          flip = 1;
 667  667  
 668  668                  op = state_to_comparison(state);
 669  669  
 670  670                  switch (flip ? flip_comparison(op) : op) {
 671  671                  case SPECIAL_EQUAL:
 672  672                  case SPECIAL_GTE:
 673  673                  case SPECIAL_UNSIGNED_GTE:
 674  674                  case '>':
 675  675                  case SPECIAL_UNSIGNED_GT:
      676 +                        if (preserve)
      677 +                                break;
 676  678                          new = alloc_compare_state(
 677  679                                          data->left, data->left_var, data->left_vsl,
 678  680                                          flip ? '<' : '>',
 679  681                                          data->right, data->right_var, data->right_vsl);
 680  682                          set_state(compare_id, tmp, NULL, new);
 681  683                          break;
 682  684                  case '<':
 683  685                  case SPECIAL_UNSIGNED_LT:
 684  686                          new = alloc_compare_state(
 685  687                                          data->left, data->left_var, data->left_vsl,
 686  688                                          flip ? SPECIAL_GTE : SPECIAL_LTE,
 687  689                                          data->right, data->right_var, data->right_vsl);
 688  690                          set_state(compare_id, tmp, NULL, new);
 689  691                          break;
 690  692                  default:
 691  693                          set_state(compare_id, tmp, NULL, &undefined);
 692  694                  }
 693  695          } END_FOR_EACH_PTR(tmp);
 694  696  }
 695  697  
 696      -static void match_dec(struct sm_state *sm)
      698 +static void match_dec(struct sm_state *sm, bool preserve)
 697  699  {
 698  700          struct string_list *links;
 699  701          struct smatch_state *state;
 700  702          char *tmp;
 701  703  
 702  704          links = sm->state->data;
 703  705  
 704  706          FOR_EACH_PTR(links, tmp) {
 705  707                  state = get_state(compare_id, tmp, NULL);
 706  708  
 707  709                  switch (state_to_comparison(state)) {
 708  710                  case SPECIAL_EQUAL:
 709  711                  case SPECIAL_LTE:
 710  712                  case SPECIAL_UNSIGNED_LTE:
 711  713                  case '<':
 712  714                  case SPECIAL_UNSIGNED_LT: {
 713  715                          struct compare_data *data = state->data;
 714  716                          struct smatch_state *new;
 715  717  
      718 +                        if (preserve)
      719 +                                break;
      720 +
 716  721                          new = alloc_compare_state(
 717  722                                          data->left, data->left_var, data->left_vsl,
 718  723                                          '<',
 719  724                                          data->right, data->right_var, data->right_vsl);
 720  725                          set_state(compare_id, tmp, NULL, new);
 721  726                          break;
 722  727                          }
 723  728                  default:
 724  729                          set_state(compare_id, tmp, NULL, &undefined);
 725  730                  }
 726  731          } END_FOR_EACH_PTR(tmp);
 727  732  }
 728  733  
      734 +static void reset_sm(struct sm_state *sm)
      735 +{
      736 +        struct string_list *links;
      737 +        char *tmp;
      738 +
      739 +        links = sm->state->data;
      740 +
      741 +        FOR_EACH_PTR(links, tmp) {
      742 +                set_state(compare_id, tmp, NULL, &undefined);
      743 +        } END_FOR_EACH_PTR(tmp);
      744 +        set_state(link_id, sm->name, sm->sym, &undefined);
      745 +}
      746 +
      747 +static bool match_add_sub_assign(struct sm_state *sm, struct expression *expr)
      748 +{
      749 +        struct range_list *rl;
      750 +        sval_t zero = { .type = &int_ctype };
      751 +
      752 +        if (!expr || expr->type != EXPR_ASSIGNMENT)
      753 +                return false;
      754 +        if (expr->op != SPECIAL_ADD_ASSIGN && expr->op != SPECIAL_SUB_ASSIGN)
      755 +                return false;
      756 +
      757 +        get_absolute_rl(expr->right, &rl);
      758 +        if (sval_is_negative(rl_min(rl))) {
      759 +                reset_sm(sm);
      760 +                return false;
      761 +        }
      762 +
      763 +        if (expr->op == SPECIAL_ADD_ASSIGN)
      764 +                match_inc(sm, rl_has_sval(rl, zero));
      765 +        else
      766 +                match_dec(sm, rl_has_sval(rl, zero));
      767 +        return true;
      768 +}
      769 +
 729  770  static void match_inc_dec(struct sm_state *sm, struct expression *mod_expr)
 730  771  {
 731  772          /*
 732  773           * if (foo > bar) then ++foo is also > bar.
 733  774           */
 734  775          if (!mod_expr)
 735  776                  return;
      777 +        if (match_add_sub_assign(sm, mod_expr))
      778 +                return;
 736  779          if (mod_expr->type != EXPR_PREOP && mod_expr->type != EXPR_POSTOP)
 737  780                  return;
 738  781  
 739  782          if (mod_expr->op == SPECIAL_INCREMENT)
 740      -                match_inc(sm);
      783 +                match_inc(sm, false);
 741  784          else if (mod_expr->op == SPECIAL_DECREMENT)
 742      -                match_dec(sm);
      785 +                match_dec(sm, false);
 743  786  }
 744  787  
 745  788  static int is_self_assign(struct expression *expr)
 746  789  {
 747  790          if (!expr || expr->type != EXPR_ASSIGNMENT || expr->op != '=')
 748  791                  return 0;
 749  792          return expr_equiv(expr->left, expr->right);
 750  793  }
 751  794  
 752  795  static void match_modify(struct sm_state *sm, struct expression *mod_expr)
 753  796  {
 754      -        struct string_list *links;
 755      -        char *tmp;
 756      -
 757  797          if (mod_expr && is_self_assign(mod_expr))
 758  798                  return;
 759  799  
 760  800          /* handled by match_inc_dec() */
 761  801          if (mod_expr &&
 762  802              ((mod_expr->type == EXPR_PREOP || mod_expr->type == EXPR_POSTOP) &&
 763  803               (mod_expr->op == SPECIAL_INCREMENT || mod_expr->op == SPECIAL_DECREMENT)))
 764  804                  return;
      805 +        if (mod_expr && mod_expr->type == EXPR_ASSIGNMENT &&
      806 +            (mod_expr->op == SPECIAL_ADD_ASSIGN || mod_expr->op == SPECIAL_SUB_ASSIGN))
      807 +                return;
 765  808  
 766      -        links = sm->state->data;
 767      -
 768      -        FOR_EACH_PTR(links, tmp) {
 769      -                set_state(compare_id, tmp, NULL, &undefined);
 770      -        } END_FOR_EACH_PTR(tmp);
 771      -        set_state(link_id, sm->name, sm->sym, &undefined);
      809 +        reset_sm(sm);
 772  810  }
 773  811  
 774  812  static void match_preop(struct expression *expr)
 775  813  {
 776  814          struct expression *parent;
 777  815          struct range_list *left, *right;
 778  816          int op;
 779  817  
 780  818          /*
 781  819           * This is an important special case.  Say you have:
↓ open down ↓ 815 lines elided ↑ open up ↑
1597 1635          state = get_state(compare_id, buf, NULL);
1598 1636          if (state)
1599 1637                  ret = state_to_comparison(state);
1600 1638  
1601 1639          if (invert)
1602 1640                  ret = flip_comparison(ret);
1603 1641  
1604 1642          return ret;
1605 1643  }
1606 1644  
1607      -int get_comparison(struct expression *a, struct expression *b)
     1645 +static int get_comparison_helper(struct expression *a, struct expression *b, bool use_extra)
1608 1646  {
1609 1647          char *one = NULL;
1610 1648          char *two = NULL;
1611 1649          int ret = 0;
1612 1650  
1613 1651          if (!a || !b)
1614 1652                  return 0;
1615 1653  
1616 1654          a = strip_parens(a);
1617 1655          b = strip_parens(b);
↓ open down ↓ 28 lines elided ↑ open up ↑
1646 1684                  ret = SPECIAL_LTE;
1647 1685          else if ((is_minus_one(a) || is_plus_one(b)) && ret == '>')
1648 1686                  ret = SPECIAL_GTE;
1649 1687          else
1650 1688                  ret = 0;
1651 1689  
1652 1690  free:
1653 1691          free_string(one);
1654 1692          free_string(two);
1655 1693  
1656      -        if (!ret)
     1694 +        if (!ret && use_extra)
1657 1695                  return comparison_from_extra(a, b);
1658 1696          return ret;
1659 1697  }
1660 1698  
     1699 +int get_comparison(struct expression *a, struct expression *b)
     1700 +{
     1701 +        return get_comparison_helper(a, b, true);
     1702 +}
     1703 +
     1704 +int get_comparison_no_extra(struct expression *a, struct expression *b)
     1705 +{
     1706 +        return get_comparison_helper(a, b, false);
     1707 +}
     1708 +
1661 1709  int possible_comparison(struct expression *a, int comparison, struct expression *b)
1662 1710  {
1663 1711          char *one = NULL;
1664 1712          char *two = NULL;
1665 1713          int ret = 0;
1666 1714          char buf[256];
1667 1715          struct sm_state *sm;
1668 1716          int saved;
1669 1717  
1670 1718          one = chunk_to_var(a);
↓ open down ↓ 649 lines elided ↑ open up ↑
2320 2368  }
2321 2369  
2322 2370  static int split_op_param_key(char *value, int *op, int *param, char **key)
2323 2371  {
2324 2372          static char buf[256];
2325 2373          char *p;
2326 2374  
2327 2375          if (!parse_comparison(&value, op))
2328 2376                  return 0;
2329 2377  
2330      -        snprintf(buf, sizeof(buf), value);
     2378 +        snprintf(buf, sizeof(buf), "%s", value);
2331 2379  
2332 2380          p = buf;
2333 2381          if (*p++ != '$')
2334 2382                  return 0;
2335 2383  
2336 2384          *param = atoi(p);
2337 2385          if (*param < 0 || *param > 99)
2338 2386                  return 0;
2339 2387          p++;
2340 2388          if (*param > 9)
↓ open down ↓ 147 lines elided ↑ open up ↑
2488 2536  static void free_data(struct symbol *sym)
2489 2537  {
2490 2538          if (__inline_fn)
2491 2539                  return;
2492 2540          clear_compare_data_alloc();
2493 2541  }
2494 2542  
2495 2543  void register_comparison(int id)
2496 2544  {
2497 2545          compare_id = id;
     2546 +        set_dynamic_states(compare_id);
2498 2547          add_hook(&save_start_states, AFTER_DEF_HOOK);
2499 2548          add_unmatched_state_hook(compare_id, unmatched_comparison);
2500 2549          add_pre_merge_hook(compare_id, &pre_merge_hook);
2501 2550          add_merge_hook(compare_id, &merge_compare_states);
2502 2551          add_hook(&free_data, AFTER_FUNC_HOOK);
2503 2552          add_hook(&match_call_info, FUNCTION_CALL_HOOK);
2504 2553          add_split_return_callback(&print_return_comparison);
2505 2554  
2506 2555          select_return_states_hook(PARAM_COMPARE, &db_return_comparison);
2507 2556          add_hook(&match_preop, OP_HOOK);
2508 2557  }
2509 2558  
2510 2559  void register_comparison_late(int id)
2511 2560  {
2512 2561          add_hook(&match_assign, ASSIGNMENT_HOOK);
2513 2562  }
2514 2563  
2515 2564  void register_comparison_links(int id)
2516 2565  {
2517 2566          link_id = id;
     2567 +        db_ignore_states(link_id);
     2568 +        set_dynamic_states(link_id);
2518 2569          add_merge_hook(link_id, &merge_links);
2519 2570          add_modification_hook(link_id, &match_modify);
2520 2571          add_modification_hook_late(link_id, match_inc_dec);
2521 2572  
2522 2573          add_member_info_callback(link_id, struct_member_callback);
2523 2574  }
2524 2575  
2525 2576  void register_comparison_inc_dec(int id)
2526 2577  {
2527 2578          inc_dec_id = id;
2528 2579          add_modification_hook_late(inc_dec_id, &iter_modify);
2529 2580  }
2530 2581  
2531 2582  void register_comparison_inc_dec_links(int id)
2532 2583  {
2533 2584          inc_dec_link_id = id;
     2585 +        set_dynamic_states(inc_dec_link_id);
2534 2586          set_up_link_functions(inc_dec_id, inc_dec_link_id);
2535 2587  }
2536 2588  
2537 2589  static void filter_by_sm(struct sm_state *sm, int op,
2538 2590                         struct state_list **true_stack,
2539 2591                         struct state_list **false_stack)
2540 2592  {
2541 2593          struct compare_data *data;
2542 2594          int istrue = 0;
2543 2595          int isfalse = 0;
↓ open down ↓ 77 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX