Print this page
11506 smatch resync

Split Close
Expand all
Collapse all
          --- old/usr/src/tools/smatch/src/smatch_ranges.c
          +++ new/usr/src/tools/smatch/src/smatch_ranges.c
↓ open down ↓ 18 lines elided ↑ open up ↑
  19   19  #include "smatch.h"
  20   20  #include "smatch_extra.h"
  21   21  #include "smatch_slist.h"
  22   22  
  23   23  ALLOCATOR(data_info, "smatch extra data");
  24   24  ALLOCATOR(data_range, "data range");
  25   25  __DO_ALLOCATOR(struct data_range, sizeof(struct data_range), __alignof__(struct data_range),
  26   26                           "permanent ranges", perm_data_range);
  27   27  __DECLARE_ALLOCATOR(struct ptr_list, rl_ptrlist);
  28   28  
       29 +static bool is_err_ptr(sval_t sval)
       30 +{
       31 +        if (option_project != PROJ_KERNEL)
       32 +                return false;
       33 +        if (!type_is_ptr(sval.type))
       34 +                return false;
       35 +        if (sval.uvalue < -4095ULL)
       36 +                return false;
       37 +        return true;
       38 +}
       39 +
       40 +static char *get_err_pointer_str(struct data_range *drange)
       41 +{
       42 +        static char buf[20];
       43 +
       44 +        /*
       45 +         * The kernel has error pointers where you do essentially:
       46 +         *
       47 +         * return (void *)(unsigned long)-12;
       48 +         *
       49 +         * But what I want here is to print -12 instead of the unsigned version
       50 +         * of that.
       51 +         *
       52 +         */
       53 +        if (!is_err_ptr(drange->min))
       54 +                return NULL;
       55 +
       56 +        if (drange->min.value == drange->max.value)
       57 +                snprintf(buf, sizeof(buf), "(%lld)", drange->min.value);
       58 +        else
       59 +                snprintf(buf, sizeof(buf), "(%lld)-(%lld)", drange->min.value, drange->max.value);
       60 +        return buf;
       61 +}
       62 +
  29   63  char *show_rl(struct range_list *list)
  30   64  {
       65 +        struct data_range *prev_drange = NULL;
  31   66          struct data_range *tmp;
  32      -        char full[512];
       67 +        char full[255];
       68 +        char *p = full;
       69 +        char *prev = full;
       70 +        char *err_ptr;
       71 +        int remain;
  33   72          int i = 0;
  34   73  
  35   74          full[0] = '\0';
  36      -        full[sizeof(full) - 1] = '\0';
       75 +
  37   76          FOR_EACH_PTR(list, tmp) {
  38      -                if (i++)
  39      -                        strncat(full, ",", 254 - strlen(full));
  40      -                if (sval_cmp(tmp->min, tmp->max) == 0) {
  41      -                        strncat(full, sval_to_str(tmp->min), 254 - strlen(full));
  42      -                        continue;
       77 +                remain = full + sizeof(full) - p;
       78 +                if (remain < 48) {
       79 +                        snprintf(prev, full + sizeof(full) - prev, ",%s-%s",
       80 +                                 sval_to_str(prev_drange->min),
       81 +                                 sval_to_str(sval_type_max(prev_drange->min.type)));
       82 +                        break;
  43   83                  }
  44      -                strncat(full, sval_to_str(tmp->min), 254 - strlen(full));
  45      -                strncat(full, "-", 254 - strlen(full));
  46      -                strncat(full, sval_to_str(tmp->max), 254 - strlen(full));
       84 +                prev_drange = tmp;
       85 +                prev = p;
       86 +
       87 +                err_ptr = get_err_pointer_str(tmp);
       88 +                if (err_ptr) {
       89 +                        p += snprintf(p, remain, "%s%s", i++ ? "," : "", err_ptr);
       90 +                } else if (sval_cmp(tmp->min, tmp->max) == 0) {
       91 +                        p += snprintf(p, remain, "%s%s", i++ ? "," : "",
       92 +                                      sval_to_str(tmp->min));
       93 +                } else {
       94 +                        p += snprintf(p, remain, "%s%s-%s", i++ ? "," : "",
       95 +                                      sval_to_str(tmp->min),
       96 +                                      sval_to_str(tmp->max));
       97 +                }
  47   98          } END_FOR_EACH_PTR(tmp);
  48      -        if (strlen(full) == sizeof(full) - 1)
  49      -                full[sizeof(full) - 2] = '+';
       99 +
  50  100          return alloc_sname(full);
  51  101  }
  52  102  
  53  103  void free_all_rl(void)
  54  104  {
  55  105          clear_rl_ptrlist_alloc();
  56  106  }
  57  107  
  58  108  static int sval_too_big(struct symbol *type, sval_t sval)
  59  109  {
↓ open down ↓ 12 lines elided ↑ open up ↑
  72  122                          return 1;
  73  123                  if (sval.value > sval_type_max(type).value)
  74  124                          return 1;
  75  125                  return 0;
  76  126          }
  77  127          if (sval.uvalue > sval_type_max(type).uvalue)
  78  128                  return 1;
  79  129          return 0;
  80  130  }
  81  131  
      132 +static int truncates_nicely(struct symbol *type, sval_t min, sval_t max)
      133 +{
      134 +        unsigned long long mask;
      135 +        int bits = type_bits(type);
      136 +
      137 +        if (bits >= type_bits(min.type))
      138 +                return 0;
      139 +
      140 +        mask = -1ULL << bits;
      141 +        return (min.uvalue & mask) == (max.uvalue & mask);
      142 +}
      143 +
  82  144  static void add_range_t(struct symbol *type, struct range_list **rl, sval_t min, sval_t max)
  83  145  {
  84  146          /* If we're just adding a number, cast it and add it */
  85  147          if (sval_cmp(min, max) == 0) {
  86  148                  add_range(rl, sval_cast(type, min), sval_cast(type, max));
  87  149                  return;
  88  150          }
  89  151  
  90  152          /* If the range is within the type range then add it */
  91  153          if (sval_fits(type, min) && sval_fits(type, max)) {
  92  154                  add_range(rl, sval_cast(type, min), sval_cast(type, max));
  93  155                  return;
  94  156          }
  95  157  
      158 +        if (truncates_nicely(type, min, max)) {
      159 +                add_range(rl, sval_cast(type, min), sval_cast(type, max));
      160 +                return;
      161 +        }
      162 +
  96  163          /*
  97  164           * If the range we are adding has more bits than the range type then
  98  165           * add the whole range type.  Eg:
  99  166           * 0x8000000000000000 - 0xf000000000000000 -> cast to int
 100      -         * This isn't totally the right thing to do.  We could be more granular.
      167 +         *
 101  168           */
 102  169          if (sval_too_big(type, min) || sval_too_big(type, max)) {
 103  170                  add_range(rl, sval_type_min(type), sval_type_max(type));
 104  171                  return;
 105  172          }
 106  173  
 107  174          /* Cast negative values to high positive values */
 108  175          if (sval_is_negative(min) && type_unsigned(type)) {
 109  176                  if (sval_is_positive(max)) {
 110  177                          if (sval_too_high(type, max)) {
↓ open down ↓ 20 lines elided ↑ open up ↑
 131  198                  max = sval_cast(type, max);
 132  199                  add_range(rl, min, max);
 133  200          }
 134  201  
 135  202          add_range(rl, sval_cast(type, min), sval_cast(type, max));
 136  203          return;
 137  204  }
 138  205  
 139  206  static int str_to_comparison_arg_helper(const char *str,
 140  207                  struct expression *call, int *comparison,
 141      -                struct expression **arg, char **endp)
      208 +                struct expression **arg, const char **endp)
 142  209  {
 143  210          int param;
 144      -        char *c = (char *)str;
      211 +        const char *c = str;
 145  212  
 146  213          if (*c != '[')
 147  214                  return 0;
 148  215          c++;
 149  216  
 150  217          if (*c == '<') {
 151  218                  c++;
 152  219                  if (*c == '=') {
 153  220                          *comparison = SPECIAL_LTE;
 154  221                          c++;
↓ open down ↓ 9 lines elided ↑ open up ↑
 164  231                  if (*c == '=') {
 165  232                          *comparison = SPECIAL_GTE;
 166  233                          c++;
 167  234                  } else {
 168  235                          *comparison = '>';
 169  236                  }
 170  237          } else if (*c == '!') {
 171  238                  c++;
 172  239                  c++;
 173  240                  *comparison = SPECIAL_NOTEQUAL;
      241 +        } else if (*c == '$') {
      242 +                *comparison = SPECIAL_EQUAL;
 174  243          } else {
 175  244                  return 0;
 176  245          }
 177  246  
 178  247          if (*c != '$')
 179  248                  return 0;
 180  249          c++;
 181  250  
 182      -        param = strtoll(c, &c, 10);
 183      -        if (*c == ']')
      251 +        param = strtoll(c, (char **)&c, 10);
      252 +        if (*c == ',' || *c == ']')
 184  253                  c++; /* skip the ']' character */
 185  254          if (endp)
 186  255                  *endp = (char *)c;
 187  256  
 188  257          if (!call)
 189  258                  return 0;
 190  259          *arg = get_argument_from_call_expr(call->args, param);
 191  260          if (!*arg)
 192  261                  return 0;
 193  262          if (*c == '-' && *(c + 1) == '>') {
↓ open down ↓ 17 lines elided ↑ open up ↑
 211  280          while (1) {
 212  281                  if (!*str)
 213  282                          return 0;
 214  283                  if (*str == '[')
 215  284                          break;
 216  285                  str++;
 217  286          }
 218  287          return str_to_comparison_arg_helper(str, call, comparison, arg, NULL);
 219  288  }
 220  289  
 221      -static int get_val_from_key(int use_max, struct symbol *type, char *c, struct expression *call, char **endp, sval_t *sval)
      290 +static int get_val_from_key(int use_max, struct symbol *type, const char *c, struct expression *call, const char **endp, sval_t *sval)
 222  291  {
 223  292          struct expression *arg;
 224  293          int comparison;
 225  294          sval_t ret, tmp;
 226  295  
 227  296          if (use_max)
 228  297                  ret = sval_type_max(type);
 229  298          else
 230  299                  ret = sval_type_min(type);
 231  300  
↓ open down ↓ 79 lines elided ↑ open up ↑
 311  380                          ret_rl = remove_range(left_orig, rl_min(right_orig), rl_min(right_orig));
 312  381                  break;
 313  382          default:
 314  383                  sm_perror("unhandled comparison %s", show_special(comparison));
 315  384                  return;
 316  385          }
 317  386  
 318  387          *rl = cast_rl(rl_type(*rl), ret_rl);
 319  388  }
 320  389  
 321      -static struct range_list *filter_by_comparison_call(char *c, struct expression *call, char **endp, struct range_list *start_rl)
      390 +static struct range_list *filter_by_comparison_call(const char *c, struct expression *call, const char **endp, struct range_list *start_rl)
 322  391  {
 323  392          struct symbol *type;
 324  393          struct expression *arg;
 325  394          struct range_list *casted_start, *right_orig;
 326  395          int comparison;
 327  396  
 328  397          if (!str_to_comparison_arg_helper(c, call, &comparison, &arg, endp))
 329  398                  return start_rl;
 330  399  
 331  400          if (!get_implied_rl(arg, &right_orig))
↓ open down ↓ 5 lines elided ↑ open up ↑
 337  406          if (type_positive_bits(rl_type(right_orig)) > type_positive_bits(type))
 338  407                  type = rl_type(right_orig);
 339  408  
 340  409          casted_start = cast_rl(type, start_rl);
 341  410          right_orig = cast_rl(type, right_orig);
 342  411  
 343  412          filter_by_comparison(&casted_start, comparison, right_orig);
 344  413          return cast_rl(rl_type(start_rl), casted_start);
 345  414  }
 346  415  
 347      -static sval_t parse_val(int use_max, struct expression *call, struct symbol *type, char *c, char **endp)
      416 +static sval_t parse_val(int use_max, struct expression *call, struct symbol *type, const char *c, const char **endp)
 348  417  {
 349      -        char *start = c;
      418 +        const char *start = c;
 350  419          sval_t ret;
 351  420  
 352  421          if (!strncmp(start, "max", 3)) {
 353  422                  ret = sval_type_max(type);
 354  423                  c += 3;
 355  424          } else if (!strncmp(start, "u64max", 6)) {
 356  425                  ret = sval_type_val(type, ULLONG_MAX);
 357  426                  c += 6;
 358  427          } else if (!strncmp(start, "s64max", 6)) {
 359  428                  ret = sval_type_val(type, LLONG_MAX);
↓ open down ↓ 31 lines elided ↑ open up ↑
 391  460          } else if (!strncmp(start, "ulong_max", 9)) {
 392  461                  ret = sval_type_val(type, ULONG_MAX);
 393  462                  c += 9;
 394  463          } else if (!strncmp(start, "ptr_max", 7)) {
 395  464                  ret = sval_type_val(type, valid_ptr_max);
 396  465                  c += 7;
 397  466          } else if (start[0] == '[') {
 398  467                  /* this parses [==p0] comparisons */
 399  468                  get_val_from_key(1, type, start, call, &c, &ret);
 400  469          } else if (type_positive_bits(type) == 64) {
 401      -                ret = sval_type_val(type, strtoull(start, &c, 0));
      470 +                ret = sval_type_val(type, strtoull(start, (char **)&c, 0));
 402  471          } else {
 403      -                ret = sval_type_val(type, strtoll(start, &c, 0));
      472 +                ret = sval_type_val(type, strtoll(start, (char **)&c, 0));
 404  473          }
 405  474          *endp = c;
 406  475          return ret;
 407  476  }
 408  477  
 409      -static char *jump_to_call_math(char *value)
      478 +static const char *jump_to_call_math(const char *value)
 410  479  {
 411      -        char *c = value;
      480 +        const char *c = value;
 412  481  
 413  482          while (*c && *c != '[')
 414  483                  c++;
 415  484  
 416  485          if (!*c)
 417  486                  return NULL;
 418  487          c++;
 419  488          if (*c == '<' || *c == '=' || *c == '>' || *c == '!')
 420  489                  return NULL;
 421  490  
 422  491          return c;
 423  492  }
 424  493  
 425      -static void str_to_rl_helper(struct expression *call, struct symbol *type, char *str, char **endp, struct range_list **rl)
      494 +static void str_to_rl_helper(struct expression *call, struct symbol *type, const char *str, const char **endp, struct range_list **rl)
 426  495  {
 427  496          struct range_list *rl_tmp = NULL;
 428      -        sval_t min, max;
 429      -        char *c;
      497 +        sval_t prev_min, min, max;
      498 +        const char *c;
 430  499  
      500 +        prev_min = sval_type_min(type);
 431  501          min = sval_type_min(type);
 432  502          max = sval_type_max(type);
 433  503          c = str;
 434  504          while (*c != '\0' && *c != '[') {
 435  505                  if (*c == '+') {
 436  506                          if (sval_cmp(min, sval_type_min(type)) != 0)
 437  507                                  min = max;
 438  508                          max = sval_type_max(type);
 439  509                          add_range_t(type, &rl_tmp, min, max);
 440  510                          break;
↓ open down ↓ 9 lines elided ↑ open up ↑
 450  520                  if (*c == '\0' || *c == '[') {
 451  521                          add_range_t(type, &rl_tmp, min, min);
 452  522                          break;
 453  523                  }
 454  524                  if (*c == ',') {
 455  525                          add_range_t(type, &rl_tmp, min, min);
 456  526                          c++;
 457  527                          continue;
 458  528                  }
 459  529                  if (*c == '+') {
 460      -                        min = sval_type_max(type);
      530 +                        min = prev_min;
      531 +                        max = sval_type_max(type);
      532 +                        add_range_t(type, &rl_tmp, min, max);
 461  533                          c++;
      534 +                        if (*c == '[' || *c == '\0')
      535 +                                break;
 462  536                  }
 463  537                  if (*c != '-') {
 464  538                          sm_msg("debug XXX: trouble parsing %s c = %s", str, c);
 465  539                          break;
 466  540                  }
 467  541                  c++;
 468  542                  if (*c == '(')
 469  543                          c++;
 470  544                  max = parse_val(1, call, type, c, &c);
 471  545                  if (!sval_fits(type, max))
 472  546                          max = sval_type_max(type);
 473  547                  if (*c == '+') {
 474  548                          max = sval_type_max(type);
      549 +                        add_range_t(type, &rl_tmp, min, max);
 475  550                          c++;
      551 +                        if (*c == '[' || *c == '\0')
      552 +                                break;
 476  553                  }
      554 +                prev_min = max;
 477  555                  add_range_t(type, &rl_tmp, min, max);
 478  556                  if (*c == ')')
 479  557                          c++;
 480  558                  if (*c == ',')
 481  559                          c++;
 482  560          }
 483  561  
 484  562          *rl = rl_tmp;
 485  563          *endp = c;
 486  564  }
 487  565  
 488      -static void str_to_dinfo(struct expression *call, struct symbol *type, char *value, struct data_info *dinfo)
      566 +static void str_to_dinfo(struct expression *call, struct symbol *type, const char *value, struct data_info *dinfo)
 489  567  {
 490  568          struct range_list *math_rl;
 491      -        char *call_math;
 492      -        char *c;
      569 +        const char *call_math;
      570 +        const char *c;
 493  571          struct range_list *rl = NULL;
 494  572  
 495  573          if (!type)
 496  574                  type = &llong_ctype;
 497  575  
 498  576          if (strcmp(value, "empty") == 0)
 499  577                  return;
 500  578  
 501  579          if (strncmp(value, "[==$", 4) == 0) {
 502  580                  struct expression *arg;
↓ open down ↓ 23 lines elided ↑ open up ↑
 526  604          if (jump_to_call_math(c) == c + 1)
 527  605                  goto cast;
 528  606  
 529  607          rl = filter_by_comparison_call(c, call, &c, rl);
 530  608  
 531  609  cast:
 532  610          rl = cast_rl(type, rl);
 533  611          dinfo->value_ranges = rl;
 534  612  }
 535  613  
      614 +static int rl_is_sane(struct range_list *rl)
      615 +{
      616 +        struct data_range *tmp;
      617 +        struct symbol *type;
      618 +
      619 +        type = rl_type(rl);
      620 +        FOR_EACH_PTR(rl, tmp) {
      621 +                if (!sval_fits(type, tmp->min))
      622 +                        return 0;
      623 +                if (!sval_fits(type, tmp->max))
      624 +                        return 0;
      625 +                if (sval_cmp(tmp->min, tmp->max) > 0)
      626 +                        return 0;
      627 +        } END_FOR_EACH_PTR(tmp);
      628 +
      629 +        return 1;
      630 +}
      631 +
 536  632  void str_to_rl(struct symbol *type, char *value, struct range_list **rl)
 537  633  {
 538  634          struct data_info dinfo = {};
 539  635  
 540  636          str_to_dinfo(NULL, type, value, &dinfo);
      637 +        if (!rl_is_sane(dinfo.value_ranges))
      638 +                dinfo.value_ranges = alloc_whole_rl(type);
 541  639          *rl = dinfo.value_ranges;
 542  640  }
 543  641  
 544      -void call_results_to_rl(struct expression *expr, struct symbol *type, char *value, struct range_list **rl)
      642 +void call_results_to_rl(struct expression *expr, struct symbol *type, const char *value, struct range_list **rl)
 545  643  {
 546  644          struct data_info dinfo = {};
 547  645  
 548  646          str_to_dinfo(strip_expr(expr), type, value, &dinfo);
 549  647          *rl = dinfo.value_ranges;
 550  648  }
 551  649  
 552  650  int is_whole_rl(struct range_list *rl)
 553  651  {
 554  652          struct data_range *drange;
 555  653  
 556  654          if (ptr_list_empty(rl))
 557  655                  return 0;
 558  656          drange = first_ptr_list((struct ptr_list *)rl);
 559  657          if (sval_is_min(drange->min) && sval_is_max(drange->max))
 560  658                  return 1;
 561  659          return 0;
 562  660  }
 563  661  
      662 +int is_unknown_ptr(struct range_list *rl)
      663 +{
      664 +        struct data_range *drange;
      665 +        int cnt = 0;
      666 +
      667 +        if (is_whole_rl(rl))
      668 +                return 1;
      669 +
      670 +        FOR_EACH_PTR(rl, drange) {
      671 +                if (++cnt >= 3)
      672 +                        return 0;
      673 +                if (sval_cmp(drange->min, valid_ptr_min_sval) == 0 &&
      674 +                    sval_cmp(drange->max, valid_ptr_max_sval) == 0)
      675 +                        return 1;
      676 +        } END_FOR_EACH_PTR(drange);
      677 +
      678 +        return 0;
      679 +}
      680 +
 564  681  int is_whole_rl_non_zero(struct range_list *rl)
 565  682  {
 566  683          struct data_range *drange;
 567  684  
 568  685          if (ptr_list_empty(rl))
 569  686                  return 0;
 570  687          drange = first_ptr_list((struct ptr_list *)rl);
 571  688          if (sval_unsigned(drange->min) &&
 572  689              drange->min.value == 1 &&
 573  690              sval_is_max(drange->max))
↓ open down ↓ 91 lines elided ↑ open up ↑
 665  782  struct range_list *alloc_whole_rl(struct symbol *type)
 666  783  {
 667  784          if (!type || type_positive_bits(type) < 0)
 668  785                  type = &llong_ctype;
 669  786          if (type->type == SYM_ARRAY)
 670  787                  type = &ptr_ctype;
 671  788  
 672  789          return alloc_rl(sval_type_min(type), sval_type_max(type));
 673  790  }
 674  791  
      792 +static bool collapse_pointer_rl(struct range_list **rl, sval_t min, sval_t max)
      793 +{
      794 +        struct range_list *new_rl = NULL;
      795 +        struct data_range *tmp;
      796 +        static bool recurse;
      797 +        bool ret = false;
      798 +        int cnt = 0;
      799 +
      800 +        /*
      801 +         * With the mtag work, then we end up getting huge lists of mtags.
      802 +         * That seems cool, but the problem is that we can only store about
      803 +         * 8-10 mtags in the DB before we truncate the list.  Also the mtags
      804 +         * aren't really used at all so it's a waste of resources for now...
      805 +         * In the future, we maybe will revisit this code.
      806 +         *
      807 +         */
      808 +
      809 +        if (recurse)
      810 +                return false;
      811 +        recurse = true;
      812 +        if (!type_is_ptr(min.type))
      813 +                goto out;
      814 +
      815 +        if (ptr_list_size((struct ptr_list *)*rl) < 8)
      816 +                goto out;
      817 +        FOR_EACH_PTR(*rl, tmp) {
      818 +                if (!is_err_ptr(tmp->min))
      819 +                        cnt++;
      820 +        } END_FOR_EACH_PTR(tmp);
      821 +        if (cnt < 8)
      822 +                goto out;
      823 +
      824 +        FOR_EACH_PTR(*rl, tmp) {
      825 +                if (sval_cmp(tmp->min, valid_ptr_min_sval) >= 0 &&
      826 +                    sval_cmp(tmp->max, valid_ptr_max_sval) <= 0)
      827 +                        add_range(&new_rl, valid_ptr_min_sval, valid_ptr_max_sval);
      828 +                else
      829 +                        add_range(&new_rl, tmp->min, tmp->max);
      830 +        } END_FOR_EACH_PTR(tmp);
      831 +
      832 +        add_range(&new_rl, min, max);
      833 +
      834 +        *rl = new_rl;
      835 +        ret = true;
      836 +out:
      837 +        recurse = false;
      838 +        return ret;
      839 +}
      840 +
 675  841  extern int rl_ptrlist_hack;
 676  842  void add_range(struct range_list **list, sval_t min, sval_t max)
 677  843  {
 678  844          struct data_range *tmp;
 679  845          struct data_range *new = NULL;
 680  846          int check_next = 0;
 681  847  
 682  848          /*
 683  849           * There is at least on valid reason why the types might be confusing
 684  850           * and that's when you have a void pointer and on some paths you treat
↓ open down ↓ 20 lines elided ↑ open up ↑
 705  871                  } else {
 706  872                          *list = cast_rl(min.type, *list);
 707  873                  }
 708  874          }
 709  875  
 710  876          if (sval_cmp(min, max) > 0) {
 711  877                  min = sval_type_min(min.type);
 712  878                  max = sval_type_max(min.type);
 713  879          }
 714  880  
      881 +        if (collapse_pointer_rl(list, min, max))
      882 +                return;
      883 +
 715  884          /*
 716  885           * FIXME:  This has a problem merging a range_list like: min-0,3-max
 717  886           * with a range like 1-2.  You end up with min-2,3-max instead of
 718  887           * just min-max.
 719  888           */
 720  889          FOR_EACH_PTR(*list, tmp) {
 721  890                  if (check_next) {
 722  891                          /* Sometimes we overlap with more than one range
 723  892                             so we have to delete or modify the next range. */
 724  893                          if (!sval_is_max(max) && max.value + 1 == tmp->min.value) {
↓ open down ↓ 487 lines elided ↑ open up ↑
1212 1381                  if (sval_cmp(min, max) > 0) {
1213 1382                          min = sval_cast(type, min);
1214 1383                          max = sval_cast(type, max);
1215 1384                  }
1216 1385                  add_range_t(type, &ret, min, max);
1217 1386          } END_FOR_EACH_PTR(tmp);
1218 1387  
1219 1388          return ret;
1220 1389  }
1221 1390  
1222      -static int rl_is_sane(struct range_list *rl)
     1391 +int rl_fits_in_type(struct range_list *rl, struct symbol *type)
1223 1392  {
1224      -        struct data_range *tmp;
1225      -        struct symbol *type;
1226      -
1227      -        type = rl_type(rl);
1228      -        FOR_EACH_PTR(rl, tmp) {
1229      -                if (!sval_fits(type, tmp->min))
1230      -                        return 0;
1231      -                if (!sval_fits(type, tmp->max))
1232      -                        return 0;
1233      -                if (sval_cmp(tmp->min, tmp->max) > 0)
1234      -                        return 0;
1235      -        } END_FOR_EACH_PTR(tmp);
1236      -
     1393 +        if (type_bits(rl_type(rl)) <= type_bits(type))
     1394 +                return 1;
     1395 +        if (sval_cmp(rl_max(rl), sval_type_max(type)) > 0)
     1396 +                return 0;
     1397 +        if (sval_is_negative(rl_min(rl)) &&
     1398 +            sval_cmp(rl_min(rl), sval_type_min(type)) < 0)
     1399 +                return 0;
1237 1400          return 1;
1238 1401  }
1239 1402  
1240 1403  static int rl_type_consistent(struct range_list *rl)
1241 1404  {
1242 1405          struct data_range *tmp;
1243 1406          struct symbol *type;
1244 1407  
1245 1408          type = rl_type(rl);
1246 1409          FOR_EACH_PTR(rl, tmp) {
↓ open down ↓ 56 lines elided ↑ open up ↑
1303 1466          FOR_EACH_PTR(rl, tmp) {
1304 1467                  add_range_t(type, &ret, tmp->min, tmp->max);
1305 1468          } END_FOR_EACH_PTR(tmp);
1306 1469  
1307 1470          if (!ret)
1308 1471                  return alloc_whole_rl(type);
1309 1472  
1310 1473          return ret;
1311 1474  }
1312 1475  
1313      -struct range_list *rl_invert(struct range_list *orig)
     1476 +struct range_list *rl_filter(struct range_list *rl, struct range_list *filter)
1314 1477  {
1315      -        struct range_list *ret = NULL;
1316 1478          struct data_range *tmp;
1317      -        sval_t gap_min, abs_max, sval;
1318 1479  
1319      -        if (!orig)
1320      -                return NULL;
1321      -        if (type_bits(rl_type(orig)) < 0)  /* void type mostly */
1322      -                return NULL;
1323      -
1324      -        gap_min = sval_type_min(rl_min(orig).type);
1325      -        abs_max = sval_type_max(rl_max(orig).type);
1326      -
1327      -        FOR_EACH_PTR(orig, tmp) {
1328      -                if (sval_cmp(tmp->min, gap_min) > 0) {
1329      -                        sval = sval_type_val(tmp->min.type, tmp->min.value - 1);
1330      -                        add_range(&ret, gap_min, sval);
1331      -                }
1332      -                if (sval_cmp(tmp->max, abs_max) == 0)
1333      -                        return ret;
1334      -                gap_min = sval_type_val(tmp->max.type, tmp->max.value + 1);
     1480 +        FOR_EACH_PTR(filter, tmp) {
     1481 +                rl = remove_range(rl, tmp->min, tmp->max);
1335 1482          } END_FOR_EACH_PTR(tmp);
1336 1483  
1337      -        if (sval_cmp(gap_min, abs_max) <= 0)
1338      -                add_range(&ret, gap_min, abs_max);
1339      -
1340      -        return ret;
     1484 +        return rl;
1341 1485  }
1342 1486  
1343      -struct range_list *rl_filter(struct range_list *rl, struct range_list *filter)
     1487 +struct range_list *do_intersection(struct range_list *one_rl, struct range_list *two_rl)
1344 1488  {
1345      -        struct data_range *tmp;
     1489 +        struct data_range *one, *two;
     1490 +        struct range_list *ret = NULL;
1346 1491  
1347      -        FOR_EACH_PTR(filter, tmp) {
1348      -                rl = remove_range(rl, tmp->min, tmp->max);
1349      -        } END_FOR_EACH_PTR(tmp);
1350 1492  
1351      -        return rl;
     1493 +        PREPARE_PTR_LIST(one_rl, one);
     1494 +        PREPARE_PTR_LIST(two_rl, two);
     1495 +
     1496 +        while (true) {
     1497 +                if (!one || !two)
     1498 +                        break;
     1499 +                if (sval_cmp(one->max, two->min) < 0) {
     1500 +                        NEXT_PTR_LIST(one);
     1501 +                        continue;
     1502 +                }
     1503 +                if (sval_cmp(one->min, two->min) < 0 && sval_cmp(one->max, two->max) <= 0) {
     1504 +                        add_range(&ret, two->min, one->max);
     1505 +                        NEXT_PTR_LIST(one);
     1506 +                        continue;
     1507 +                }
     1508 +                if (sval_cmp(one->min, two->min) >= 0 && sval_cmp(one->max, two->max) <= 0) {
     1509 +                        add_range(&ret, one->min, one->max);
     1510 +                        NEXT_PTR_LIST(one);
     1511 +                        continue;
     1512 +                }
     1513 +                if (sval_cmp(one->min, two->min) < 0 && sval_cmp(one->max, two->max) > 0) {
     1514 +                        add_range(&ret, two->min, two->max);
     1515 +                        NEXT_PTR_LIST(two);
     1516 +                        continue;
     1517 +                }
     1518 +                if (sval_cmp(one->min, two->max) <= 0 && sval_cmp(one->max, two->max) > 0) {
     1519 +                        add_range(&ret, one->min, two->max);
     1520 +                        NEXT_PTR_LIST(two);
     1521 +                        continue;
     1522 +                }
     1523 +                if (sval_cmp(one->min, two->max) <= 0) {
     1524 +                        sm_fatal("error calculating intersection of '%s' and '%s'", show_rl(one_rl), show_rl(two_rl));
     1525 +                        return NULL;
     1526 +                }
     1527 +                NEXT_PTR_LIST(two);
     1528 +        }
     1529 +
     1530 +        FINISH_PTR_LIST(two);
     1531 +        FINISH_PTR_LIST(one);
     1532 +
     1533 +        return ret;
1352 1534  }
1353 1535  
1354 1536  struct range_list *rl_intersection(struct range_list *one, struct range_list *two)
1355 1537  {
1356      -        struct range_list *one_orig;
1357      -        struct range_list *two_orig;
1358 1538          struct range_list *ret;
1359 1539          struct symbol *ret_type;
1360 1540          struct symbol *small_type;
1361 1541          struct symbol *large_type;
1362 1542  
1363      -        if (!two)
     1543 +        if (!one || !two)
1364 1544                  return NULL;
1365      -        if (!one)
1366      -                return NULL;
1367 1545  
1368      -        one_orig = one;
1369      -        two_orig = two;
1370      -
1371 1546          ret_type = rl_type(one);
1372 1547          small_type = rl_type(one);
1373 1548          large_type = rl_type(two);
1374 1549  
1375 1550          if (type_bits(rl_type(two)) < type_bits(small_type)) {
1376 1551                  small_type = rl_type(two);
1377 1552                  large_type = rl_type(one);
1378 1553          }
1379 1554  
1380 1555          one = cast_rl(large_type, one);
1381 1556          two = cast_rl(large_type, two);
1382 1557  
1383      -        ret = one;
1384      -        one = rl_invert(one);
1385      -        two = rl_invert(two);
1386      -
1387      -        ret = rl_filter(ret, one);
1388      -        ret = rl_filter(ret, two);
1389      -
1390      -        one = cast_rl(small_type, one_orig);
1391      -        two = cast_rl(small_type, two_orig);
1392      -
1393      -        one = rl_invert(one);
1394      -        two = rl_invert(two);
1395      -
1396      -        ret = cast_rl(small_type, ret);
1397      -        ret = rl_filter(ret, one);
1398      -        ret = rl_filter(ret, two);
1399      -
     1558 +        ret = do_intersection(one, two);
1400 1559          return cast_rl(ret_type, ret);
1401 1560  }
1402 1561  
1403 1562  static struct range_list *handle_mod_rl(struct range_list *left, struct range_list *right)
1404 1563  {
1405 1564          sval_t zero;
1406 1565          sval_t max;
1407 1566  
1408 1567          max = rl_max(right);
1409 1568          if (sval_is_max(max))
↓ open down ↓ 103 lines elided ↑ open up ↑
1513 1672          neg_neg = divide_rl_helper(left_neg, right_neg);
1514 1673          neg_pos = divide_rl_helper(left_neg, right_pos);
1515 1674          pos_neg = divide_rl_helper(left_pos, right_neg);
1516 1675          pos_pos = divide_rl_helper(left_pos, right_pos);
1517 1676  
1518 1677          ret = rl_union(neg_neg, neg_pos);
1519 1678          ret = rl_union(ret, pos_neg);
1520 1679          return rl_union(ret, pos_pos);
1521 1680  }
1522 1681  
     1682 +static struct range_list *ptr_add_mult(struct range_list *left, int op, struct range_list *right)
     1683 +{
     1684 +        struct range_list *ret;
     1685 +        sval_t l_sval, r_sval, res;
     1686 +
     1687 +        /*
     1688 +         * This function is sort of the wrong API because it takes two pointer
     1689 +         * and adds them together.  The caller is expected to figure out
     1690 +         * alignment.  Neither of those are the correct things to do.
     1691 +         *
     1692 +         * Really this function is quite bogus...
     1693 +         */
     1694 +
     1695 +        if (rl_to_sval(left, &l_sval) && rl_to_sval(right, &r_sval)) {
     1696 +                res = sval_binop(l_sval, op, r_sval);
     1697 +                return alloc_rl(res, res);
     1698 +        }
     1699 +
     1700 +        if (rl_min(left).value != 0 || rl_max(right).value != 0) {
     1701 +                ret = alloc_rl(valid_ptr_min_sval, valid_ptr_max_sval);
     1702 +                return cast_rl(rl_type(left), ret);
     1703 +        }
     1704 +
     1705 +        return alloc_whole_rl(rl_type(left));
     1706 +}
     1707 +
1523 1708  static struct range_list *handle_add_mult_rl(struct range_list *left, int op, struct range_list *right)
1524 1709  {
1525 1710          sval_t min, max;
1526 1711  
     1712 +        if (type_is_ptr(rl_type(left)) || type_is_ptr(rl_type(right)))
     1713 +                return ptr_add_mult(left, op, right);
     1714 +
1527 1715          if (sval_binop_overflows(rl_min(left), op, rl_min(right)))
1528 1716                  return NULL;
1529 1717          min = sval_binop(rl_min(left), op, rl_min(right));
1530 1718  
1531 1719          if (sval_binop_overflows(rl_max(left), op, rl_max(right)))
1532 1720                  return NULL;
1533 1721          max = sval_binop(rl_max(left), op, rl_max(right));
1534 1722  
1535 1723          return alloc_rl(min, max);
1536 1724  }
↓ open down ↓ 101 lines elided ↑ open up ↑
1638 1826          right_set = rl_bits_always_set(right);
1639 1827          right_maybe = rl_bits_maybe_set(right);
1640 1828  
1641 1829          zero = max = rl_min(left);
1642 1830          zero.uvalue = 0;
1643 1831          max.uvalue = fls_mask((left_maybe | right_maybe) ^ (left_set & right_set));
1644 1832  
1645 1833          return cast_rl(rl_type(left), alloc_rl(zero, max));
1646 1834  }
1647 1835  
     1836 +static sval_t sval_lowest_set_bit(sval_t sval)
     1837 +{
     1838 +        sval_t ret = { .type = sval.type };
     1839 +        int i;
     1840 +
     1841 +        for (i = 0; i < 64; i++) {
     1842 +                if (sval.uvalue & 1ULL << i) {
     1843 +                        ret.uvalue = (1ULL << i);
     1844 +                        return ret;
     1845 +                }
     1846 +        }
     1847 +        return ret;
     1848 +}
     1849 +
     1850 +static struct range_list *handle_AND_rl_sval(struct range_list *rl, sval_t sval)
     1851 +{
     1852 +        struct range_list *known_rl;
     1853 +        sval_t zero = { 0 };
     1854 +        sval_t min;
     1855 +
     1856 +        zero.type = sval.type;
     1857 +        zero.value = 0;
     1858 +
     1859 +        if (sm_fls64(rl_max(rl).uvalue) < find_first_zero_bit(sval.uvalue) &&
     1860 +            sm_fls64(rl_min(rl).uvalue) < find_first_zero_bit(sval.uvalue))
     1861 +                return rl;
     1862 +
     1863 +        min = sval_lowest_set_bit(sval);
     1864 +
     1865 +        if (min.value != 0) {
     1866 +                sval_t max, mod;
     1867 +
     1868 +                max = rl_max(rl);
     1869 +                mod = sval_binop(max, '%', min);
     1870 +                if (mod.value) {
     1871 +                        max = sval_binop(max, '-', mod);
     1872 +                        max.value++;
     1873 +                        if (max.value > 0 && sval_cmp(max, rl_max(rl)) < 0)
     1874 +                                rl = remove_range(rl, max, rl_max(rl));
     1875 +                }
     1876 +        }
     1877 +
     1878 +        known_rl = alloc_rl(min, sval);
     1879 +
     1880 +        rl = rl_intersection(rl, known_rl);
     1881 +        zero = rl_min(rl);
     1882 +        zero.value = 0;
     1883 +        add_range(&rl, zero, zero);
     1884 +
     1885 +        return rl;
     1886 +}
     1887 +
     1888 +static struct range_list *fudge_AND_rl(struct range_list *rl)
     1889 +{
     1890 +        struct range_list *ret;
     1891 +        sval_t min;
     1892 +
     1893 +        min = sval_lowest_set_bit(rl_min(rl));
     1894 +        ret = clone_rl(rl);
     1895 +        add_range(&ret, min, rl_min(rl));
     1896 +
     1897 +        return ret;
     1898 +}
     1899 +
1648 1900  static struct range_list *handle_AND_rl(struct range_list *left, struct range_list *right)
1649 1901  {
1650      -        unsigned long long left_set, left_maybe;
1651      -        unsigned long long right_set, right_maybe;
1652      -        sval_t zero, max;
     1902 +        sval_t sval, zero;
     1903 +        struct range_list *rl;
1653 1904  
1654      -        return NULL;
     1905 +        if (rl_to_sval(left, &sval))
     1906 +                return handle_AND_rl_sval(right, sval);
     1907 +        if (rl_to_sval(right, &sval))
     1908 +                return handle_AND_rl_sval(left, sval);
1655 1909  
1656      -        left_set = rl_bits_always_set(left);
1657      -        left_maybe = rl_bits_maybe_set(left);
     1910 +        left = fudge_AND_rl(left);
     1911 +        right = fudge_AND_rl(right);
1658 1912  
1659      -        right_set = rl_bits_always_set(right);
1660      -        right_maybe = rl_bits_maybe_set(right);
     1913 +        rl = rl_intersection(left, right);
     1914 +        zero = rl_min(rl);
     1915 +        zero.value = 0;
     1916 +        add_range(&rl, zero, zero);
1661 1917  
1662      -        zero = max = rl_min(left);
1663      -        zero.uvalue = 0;
1664      -        max.uvalue = fls_mask((left_maybe | right_maybe) ^ (left_set & right_set));
     1918 +        return rl;
     1919 +}
1665 1920  
1666      -        return cast_rl(rl_type(left), alloc_rl(zero, max));
     1921 +static struct range_list *handle_lshift(struct range_list *left_orig, struct range_list *right_orig)
     1922 +{
     1923 +        struct range_list *left;
     1924 +        struct data_range *tmp;
     1925 +        struct range_list *ret = NULL;
     1926 +        sval_t zero = { .type = rl_type(left_orig), };
     1927 +        sval_t shift, min, max;
     1928 +        bool add_zero = false;
     1929 +
     1930 +        if (!rl_to_sval(right_orig, &shift) || sval_is_negative(shift))
     1931 +                return NULL;
     1932 +        if (shift.value == 0)
     1933 +                return left_orig;
     1934 +
     1935 +        /* Cast to unsigned for easier left shift math */
     1936 +        if (type_positive_bits(rl_type(left_orig)) < 32)
     1937 +                left = cast_rl(&uint_ctype, left_orig);
     1938 +        else if(type_positive_bits(rl_type(left_orig)) == 63)
     1939 +                left = cast_rl(&ullong_ctype, left_orig);
     1940 +        else
     1941 +                left = left_orig;
     1942 +
     1943 +        FOR_EACH_PTR(left, tmp) {
     1944 +                min = tmp->min;
     1945 +                max = tmp->max;
     1946 +
     1947 +                if (min.value == 0 || max.value > sval_type_max(max.type).uvalue >> shift.uvalue)
     1948 +                        add_zero = true;
     1949 +                if (min.value == 0 && max.value == 0)
     1950 +                        continue;
     1951 +                if (min.value == 0)
     1952 +                        min.value = 1;
     1953 +                min = sval_binop(min, SPECIAL_LEFTSHIFT, shift);
     1954 +                max = sval_binop(max, SPECIAL_LEFTSHIFT, shift);
     1955 +                add_range(&ret, min, max);
     1956 +        } END_FOR_EACH_PTR(tmp);
     1957 +
     1958 +        if (!rl_fits_in_type(ret, rl_type(left_orig)))
     1959 +                add_zero = true;
     1960 +        ret = cast_rl(rl_type(left_orig), ret);
     1961 +        if (add_zero)
     1962 +                add_range(&ret, zero, zero);
     1963 +
     1964 +        return ret;
1667 1965  }
1668 1966  
     1967 +static struct range_list *handle_rshift(struct range_list *left_orig, struct range_list *right_orig)
     1968 +{
     1969 +        struct data_range *tmp;
     1970 +        struct range_list *ret = NULL;
     1971 +        sval_t shift, min, max;
     1972 +
     1973 +        if (!rl_to_sval(right_orig, &shift) || sval_is_negative(shift))
     1974 +                return NULL;
     1975 +        if (shift.value == 0)
     1976 +                return left_orig;
     1977 +
     1978 +        FOR_EACH_PTR(left_orig, tmp) {
     1979 +                min = sval_binop(tmp->min, SPECIAL_RIGHTSHIFT, shift);
     1980 +                max = sval_binop(tmp->max, SPECIAL_RIGHTSHIFT, shift);
     1981 +                add_range(&ret, min, max);
     1982 +        } END_FOR_EACH_PTR(tmp);
     1983 +
     1984 +        return ret;
     1985 +}
     1986 +
1669 1987  struct range_list *rl_binop(struct range_list *left, int op, struct range_list *right)
1670 1988  {
1671 1989          struct symbol *cast_type;
1672 1990          sval_t left_sval, right_sval;
1673 1991          struct range_list *ret = NULL;
1674 1992  
1675 1993          cast_type = rl_type(left);
1676 1994          if (sval_type_max(rl_type(left)).uvalue < sval_type_max(rl_type(right)).uvalue)
1677 1995                  cast_type = rl_type(right);
1678 1996          if (sval_type_max(cast_type).uvalue < INT_MAX)
↓ open down ↓ 26 lines elided ↑ open up ↑
1705 2023                  break;
1706 2024          case '^':
1707 2025                  ret = handle_XOR_rl(left, right);
1708 2026                  break;
1709 2027          case '&':
1710 2028                  ret = handle_AND_rl(left, right);
1711 2029                  break;
1712 2030          case '-':
1713 2031                  ret = handle_sub_rl(left, right);
1714 2032                  break;
1715      -        /* FIXME:  Do the rest as well */
1716 2033          case SPECIAL_RIGHTSHIFT:
     2034 +                return handle_rshift(left, right);
1717 2035          case SPECIAL_LEFTSHIFT:
1718      -                break;
     2036 +                return handle_lshift(left, right);
1719 2037          }
1720 2038  
1721 2039          return ret;
1722 2040  }
1723 2041  
1724 2042  void free_data_info_allocs(void)
1725 2043  {
1726 2044          struct allocator_struct *desc = &data_info_allocator;
1727 2045          struct allocation_blob *blob = desc->blobs;
1728 2046  
↓ open down ↓ 116 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX