Print this page
11506 smatch resync

Split Close
Expand all
Collapse all
          --- old/usr/src/tools/smatch/src/smatch_buf_comparison.c
          +++ new/usr/src/tools/smatch/src/smatch_buf_comparison.c
↓ open down ↓ 21 lines elided ↑ open up ↑
  22   22   */
  23   23  
  24   24  #include "smatch.h"
  25   25  #include "smatch_extra.h"
  26   26  #include "smatch_slist.h"
  27   27  
  28   28  static int size_id;
  29   29  static int link_id;
  30   30  
  31   31  /*
  32      - * We need this for code which does:
       32 + * There is a bunch of code which does this:
  33   33   *
  34   34   *     if (size)
  35   35   *         foo = malloc(size);
  36   36   *
  37      - * We want to record that the size of "foo" is "size" even after the merge.
       37 + * So if "size" is non-zero then the size of "foo" is size.  But really it's
       38 + * also true if size is zero.  It's just better to assume to not trample over
       39 + * the data that we have by merging &undefined states.
  38   40   *
  39   41   */
  40   42  static struct smatch_state *unmatched_state(struct sm_state *sm)
  41   43  {
  42      -        struct expression *size_expr;
  43      -        sval_t sval;
  44      -
  45      -        if (!sm->state->data)
  46      -                return &undefined;
  47      -        size_expr = sm->state->data;
  48      -        if (!get_implied_value(size_expr, &sval) || sval.value != 0)
  49      -                return &undefined;
  50   44          return sm->state;
  51   45  }
  52   46  
  53   47  static struct smatch_state *merge_links(struct smatch_state *s1, struct smatch_state *s2)
  54   48  {
  55   49          struct expression *expr1, *expr2;
  56   50  
  57   51          expr1 = s1->data;
  58   52          expr2 = s2->data;
  59   53  
↓ open down ↓ 15 lines elided ↑ open up ↑
  75   69          }
  76   70  
  77   71          FOR_EACH_PTR(sm->possible, tmp) {
  78   72                  expr = tmp->state->data;
  79   73                  if (expr)
  80   74                          set_state_expr(size_id, expr, &undefined);
  81   75          } END_FOR_EACH_PTR(tmp);
  82   76          set_state(link_id, sm->name, sm->sym, &undefined);
  83   77  }
  84   78  
  85      -static struct smatch_state *alloc_expr_state(struct expression *expr)
       79 +static const char *limit_map[] = {
       80 +        "byte_count",
       81 +        "elem_count",
       82 +        "elem_last",
       83 +        "used_count",
       84 +        "used_last",
       85 +};
       86 +
       87 +int state_to_limit(struct smatch_state *state)
  86   88  {
       89 +        int i;
       90 +
       91 +        if (!state || !state->data)
       92 +                return -1;
       93 +
       94 +        for (i = 0; i < ARRAY_SIZE(limit_map); i++) {
       95 +                if (strncmp(state->name, limit_map[i], strlen(limit_map[i])) == 0)
       96 +                        return i + BYTE_COUNT;
       97 +        }
       98 +
       99 +        return -1;
      100 +}
      101 +
      102 +const char *limit_type_str(unsigned int limit_type)
      103 +{
      104 +        if (limit_type - BYTE_COUNT >= ARRAY_SIZE(limit_map)) {
      105 +                sm_msg("internal: wrong size type %u", limit_type);
      106 +                return "unknown";
      107 +        }
      108 +
      109 +        return limit_map[limit_type - BYTE_COUNT];
      110 +}
      111 +
      112 +static struct smatch_state *alloc_compare_size(int limit_type, struct expression *expr)
      113 +{
  87  114          struct smatch_state *state;
  88  115          char *name;
      116 +        char buf[256];
  89  117  
  90  118          state = __alloc_smatch_state(0);
  91  119          expr = strip_expr(expr);
  92  120          name = expr_to_str(expr);
  93      -        state->name = alloc_sname(name);
      121 +        snprintf(buf, sizeof(buf), "%s %s", limit_type_str(limit_type), name);
      122 +        state->name = alloc_sname(buf);
  94  123          free_string(name);
  95  124          state->data = expr;
  96  125          return state;
  97  126  }
  98  127  
  99  128  static int bytes_per_element(struct expression *expr)
 100  129  {
 101  130          struct symbol *type;
 102  131  
 103  132          type = get_type(expr);
 104  133          if (!type)
 105  134                  return 0;
 106  135  
 107  136          if (type->type != SYM_PTR && type->type != SYM_ARRAY)
 108  137                  return 0;
 109  138  
 110  139          type = get_base_type(type);
 111  140          return type_bytes(type);
 112  141  }
 113  142  
 114      -static void db_save_type_links(struct expression *array, struct expression *size)
      143 +static void db_save_type_links(struct expression *array, int type_limit, struct expression *size)
 115  144  {
 116  145          const char *array_name;
 117  146  
 118  147          array_name = get_data_info_name(array);
 119  148          if (!array_name)
 120  149                  array_name = "";
 121      -        sql_insert_data_info(size, ARRAY_LEN, array_name);
      150 +        sql_insert_data_info(size, type_limit, array_name);
 122  151  }
 123  152  
 124  153  static void match_alloc_helper(struct expression *pointer, struct expression *size)
 125  154  {
 126  155          struct expression *tmp;
 127  156          struct sm_state *sm;
      157 +        int limit_type = ELEM_COUNT;
 128  158          sval_t sval;
 129  159          int cnt = 0;
 130  160  
 131  161          pointer = strip_expr(pointer);
 132  162          size = strip_expr(size);
 133  163          if (!size || !pointer)
 134  164                  return;
 135  165  
 136  166          while ((tmp = get_assigned_expr(size))) {
 137  167                  size = strip_expr(tmp);
↓ open down ↓ 14 lines elided ↑ open up ↑
 152  182                      sval.value == bytes_per_element(pointer))
 153  183                          size = mult_left;
 154  184                  else
 155  185                          return;
 156  186          }
 157  187  
 158  188          /* Only save links to variables, not fixed sizes */
 159  189          if (get_value(size, &sval))
 160  190                  return;
 161  191  
 162      -        db_save_type_links(pointer, size);
 163      -        sm = set_state_expr(size_id, pointer, alloc_expr_state(size));
      192 +        if (size->type == EXPR_BINOP && size->op == '+' &&
      193 +            get_value(size->right, &sval) && sval.value == 1) {
      194 +                size = size->left;
      195 +                limit_type = ELEM_LAST;
      196 +        }
      197 +
      198 +        db_save_type_links(pointer, limit_type, size);
      199 +        sm = set_state_expr(size_id, pointer, alloc_compare_size(limit_type, size));
 164  200          if (!sm)
 165  201                  return;
 166      -        set_state_expr(link_id, size, alloc_expr_state(pointer));
      202 +        set_state_expr(link_id, size, alloc_state_expr(pointer));
 167  203  }
 168  204  
 169  205  static void match_alloc(const char *fn, struct expression *expr, void *_size_arg)
 170  206  {
 171  207          int size_arg = PTR_INT(_size_arg);
 172  208          struct expression *pointer, *call, *arg;
 173  209  
 174  210          pointer = strip_expr(expr->left);
 175  211          call = strip_expr(expr->right);
 176  212          arg = get_argument_from_call_expr(call->args, size_arg);
 177  213          match_alloc_helper(pointer, arg);
 178  214  }
 179  215  
 180  216  static void match_calloc(const char *fn, struct expression *expr, void *_start_arg)
 181  217  {
 182  218          int start_arg = PTR_INT(_start_arg);
 183  219          struct expression *pointer, *call, *arg;
 184  220          struct sm_state *tmp;
      221 +        int limit_type = ELEM_COUNT;
 185  222          sval_t sval;
 186  223  
 187  224          pointer = strip_expr(expr->left);
 188  225          call = strip_expr(expr->right);
 189  226          arg = get_argument_from_call_expr(call->args, start_arg);
 190  227          if (get_implied_value(arg, &sval) &&
 191  228              sval.value == bytes_per_element(pointer))
 192  229                  arg = get_argument_from_call_expr(call->args, start_arg + 1);
 193  230  
 194      -        db_save_type_links(pointer, arg);
 195      -        tmp = set_state_expr(size_id, pointer, alloc_expr_state(arg));
      231 +        if (arg->type == EXPR_BINOP && arg->op == '+' &&
      232 +            get_value(arg->right, &sval) && sval.value == 1) {
      233 +                arg = arg->left;
      234 +                limit_type = ELEM_LAST;
      235 +        }
      236 +
      237 +        db_save_type_links(pointer, limit_type, arg);
      238 +        tmp = set_state_expr(size_id, pointer, alloc_compare_size(limit_type, arg));
 196  239          if (!tmp)
 197  240                  return;
 198      -        set_state_expr(link_id, arg, alloc_expr_state(pointer));
      241 +        set_state_expr(link_id, arg, alloc_state_expr(pointer));
 199  242  }
 200  243  
 201      -struct expression *get_size_variable(struct expression *buf)
      244 +struct expression *get_size_variable(struct expression *buf, int *limit_type)
 202  245  {
 203  246          struct smatch_state *state;
 204  247  
 205  248          state = get_state_expr(size_id, buf);
 206      -        if (state)
 207      -                return state->data;
 208      -        return NULL;
      249 +        if (!state)
      250 +                return NULL;
      251 +        *limit_type = state_to_limit(state);
      252 +        return state->data;
 209  253  }
 210  254  
 211  255  struct expression *get_array_variable(struct expression *size)
 212  256  {
 213  257          struct smatch_state *state;
 214  258  
 215  259          state = get_state_expr(link_id, size);
 216  260          if (state)
 217  261                  return state->data;
 218  262          return NULL;
 219  263  }
 220  264  
 221  265  static void array_check(struct expression *expr)
 222  266  {
 223  267          struct expression *array;
 224  268          struct expression *size;
 225  269          struct expression *offset;
 226  270          char *array_str, *offset_str;
      271 +        int limit_type;
 227  272  
 228  273          expr = strip_expr(expr);
 229  274          if (!is_array(expr))
 230  275                  return;
 231  276  
 232  277          array = get_array_base(expr);
 233      -        size = get_size_variable(array);
      278 +        size = get_size_variable(array, &limit_type);
 234  279          if (!size)
 235  280                  return;
      281 +        if (limit_type != ELEM_COUNT)
      282 +                return;
 236  283          offset = get_array_offset(expr);
 237  284          if (!possible_comparison(size, SPECIAL_EQUAL, offset))
 238  285                  return;
 239  286  
 240  287          array_str = expr_to_str(array);
 241  288          offset_str = expr_to_str(offset);
 242  289          sm_warning("potentially one past the end of array '%s[%s]'", array_str, offset_str);
 243  290          free_string(array_str);
 244  291          free_string(offset_str);
 245  292  }
↓ open down ↓ 64 lines elided ↑ open up ↑
 310  357          if (!size_name)
 311  358                  return 0;
 312  359  
 313  360          run_sql(db_limitter_callback, &db_info,
 314  361                  "select value from data_info where type = %d and data = '%s';",
 315  362                  ARRAY_LEN, size_name);
 316  363  
 317  364          return db_info.ret;
 318  365  }
 319  366  
 320      -static int known_access_ok_comparison(struct expression *expr)
      367 +int buf_comparison_index_ok(struct expression *expr)
 321  368  {
 322  369          struct expression *array;
 323  370          struct expression *size;
 324  371          struct expression *offset;
      372 +        int limit_type;
 325  373          int comparison;
 326  374  
 327  375          array = get_array_base(expr);
 328      -        size = get_size_variable(array);
      376 +        size = get_size_variable(array, &limit_type);
 329  377          if (!size)
 330  378                  return 0;
 331  379          offset = get_array_offset(expr);
 332      -        comparison = get_comparison(size, offset);
 333      -        if (comparison == '>' || comparison == SPECIAL_UNSIGNED_GT)
      380 +        comparison = get_comparison(offset, size);
      381 +        if (!comparison)
      382 +                return 0;
      383 +
      384 +        if ((limit_type == ELEM_COUNT || limit_type == ELEM_LAST) &&
      385 +            (comparison == '<' || comparison == SPECIAL_UNSIGNED_LT))
 334  386                  return 1;
      387 +        if (limit_type == ELEM_LAST &&
      388 +            (comparison == SPECIAL_LTE ||
      389 +             comparison == SPECIAL_UNSIGNED_LTE ||
      390 +             comparison == SPECIAL_EQUAL))
      391 +                return 1;
 335  392  
 336  393          return 0;
 337  394  }
 338  395  
 339  396  static int known_access_ok_numbers(struct expression *expr)
 340  397  {
 341  398          struct expression *array;
 342  399          struct expression *offset;
 343  400          sval_t max;
 344  401          int size;
↓ open down ↓ 20 lines elided ↑ open up ↑
 365  422          struct compare_data *comp;
 366  423          char *offset_name;
 367  424          const char *equal_name = NULL;
 368  425  
 369  426          expr = strip_expr(expr);
 370  427          if (!is_array(expr))
 371  428                  return;
 372  429  
 373  430          if (known_access_ok_numbers(expr))
 374  431                  return;
 375      -        if (known_access_ok_comparison(expr))
      432 +        if (buf_comparison_index_ok(expr))
 376  433                  return;
 377  434  
 378  435          array = get_array_base(expr);
 379  436          offset = get_array_offset(expr);
 380  437          offset_name = expr_to_var(offset);
 381  438          if (!offset_name)
 382  439                  return;
 383  440          slist = get_all_possible_equal_comparisons(offset);
 384  441          if (!slist)
 385  442                  goto free;
↓ open down ↓ 23 lines elided ↑ open up ↑
 409  466  free:
 410  467          free_slist(&slist);
 411  468          free_string(offset_name);
 412  469  }
 413  470  
 414  471  static void add_allocation_function(const char *func, void *call_back, int param)
 415  472  {
 416  473          add_function_assign_hook(func, call_back, INT_PTR(param));
 417  474  }
 418  475  
 419      -static char *buf_size_param_comparison(struct expression *array, struct expression_list *args)
      476 +static int is_sizeof(struct expression *expr)
 420  477  {
 421      -        struct expression *arg;
      478 +        const char *name;
      479 +
      480 +        if (expr->type == EXPR_SIZEOF)
      481 +                return 1;
      482 +        name = pos_ident(expr->pos);
      483 +        if (name && strcmp(name, "sizeof") == 0)
      484 +                return 1;
      485 +        return 0;
      486 +}
      487 +
      488 +static int match_size_binop(struct expression *size, struct expression *expr, int *limit_type)
      489 +{
      490 +        int orig_type = *limit_type;
      491 +        struct expression *left;
      492 +        sval_t sval;
      493 +
      494 +        left = expr->left;
      495 +        if (!expr_equiv(size, left))
      496 +                return 0;
      497 +
      498 +        if (expr->op == '-' &&
      499 +            get_value(expr->right, &sval) &&
      500 +            sval.value == 1 &&
      501 +            orig_type == ELEM_COUNT) {
      502 +                *limit_type = ELEM_LAST;
      503 +                return 1;
      504 +        }
      505 +
      506 +        if (expr->op == '+' &&
      507 +            get_value(expr->right, &sval) &&
      508 +            sval.value == 1 &&
      509 +            orig_type == ELEM_LAST) {
      510 +                *limit_type = ELEM_COUNT;
      511 +                return 1;
      512 +        }
      513 +
      514 +        if (expr->op == '*' &&
      515 +            is_sizeof(expr->right) &&
      516 +            orig_type == ELEM_COUNT) {
      517 +                *limit_type = BYTE_COUNT;
      518 +                return 1;
      519 +        }
      520 +
      521 +        if (expr->op == '/' &&
      522 +            is_sizeof(expr->right) &&
      523 +            orig_type == BYTE_COUNT) {
      524 +                *limit_type = ELEM_COUNT;
      525 +                return 1;
      526 +        }
      527 +
      528 +        return 0;
      529 +}
      530 +
      531 +static char *buf_size_param_comparison(struct expression *array, struct expression_list *args, int *limit_type)
      532 +{
      533 +        struct expression *tmp, *arg;
 422  534          struct expression *size;
 423  535          static char buf[32];
 424  536          int i;
 425  537  
 426      -        size = get_size_variable(array);
      538 +        size = get_size_variable(array, limit_type);
 427  539          if (!size)
 428  540                  return NULL;
 429  541  
      542 +        if (*limit_type == USED_LAST)
      543 +                *limit_type = ELEM_LAST;
      544 +        if (*limit_type == USED_COUNT)
      545 +                *limit_type = ELEM_COUNT;
      546 +
 430  547          i = -1;
 431      -        FOR_EACH_PTR(args, arg) {
      548 +        FOR_EACH_PTR(args, tmp) {
 432  549                  i++;
      550 +                arg = tmp;
 433  551                  if (arg == array)
 434  552                          continue;
 435      -                if (!expr_equiv(arg, size))
 436      -                        continue;
 437      -                snprintf(buf, sizeof(buf), "==$%d", i);
 438      -                return buf;
 439      -        } END_FOR_EACH_PTR(arg);
      553 +                if (expr_equiv(arg, size) ||
      554 +                    (arg->type == EXPR_BINOP &&
      555 +                     match_size_binop(size, arg, limit_type))) {
      556 +                        snprintf(buf, sizeof(buf), "==$%d", i);
      557 +                        return buf;
      558 +                }
      559 +        } END_FOR_EACH_PTR(tmp);
 440  560  
 441  561          return NULL;
 442  562  }
 443  563  
 444  564  static void match_call(struct expression *call)
 445  565  {
 446  566          struct expression *arg;
 447  567          char *compare;
 448  568          int param;
      569 +        char buf[5];
      570 +        int limit_type;
 449  571  
 450  572          param = -1;
 451  573          FOR_EACH_PTR(call->args, arg) {
 452  574                  param++;
 453  575                  if (!is_pointer(arg))
 454  576                          continue;
 455      -                compare = buf_size_param_comparison(arg, call->args);
      577 +                compare = buf_size_param_comparison(arg, call->args, &limit_type);
 456  578                  if (!compare)
 457  579                          continue;
 458      -                sql_insert_caller_info(call, ARRAY_LEN, param, "$", compare);
      580 +                snprintf(buf, sizeof(buf), "%d", limit_type);
      581 +                sql_insert_caller_info(call, limit_type, param, compare, buf);
 459  582          } END_FOR_EACH_PTR(arg);
 460  583  }
 461  584  
 462  585  static int get_param(int param, char **name, struct symbol **sym)
 463  586  {
 464  587          struct symbol *arg;
 465  588          int i;
 466  589  
 467  590          i = 0;
 468  591          FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
↓ open down ↓ 19 lines elided ↑ open up ↑
 488  611  }
 489  612  
 490  613  static void set_param_compare(const char *array_name, struct symbol *array_sym, char *key, char *value)
 491  614  {
 492  615          struct expression *array_expr;
 493  616          struct expression *size_expr;
 494  617          struct symbol *size_sym;
 495  618          char *size_name;
 496  619          long param;
 497  620          struct sm_state *tmp;
      621 +        int limit_type;
 498  622  
 499      -        if (strncmp(value, "==$", 3) != 0)
      623 +        if (strncmp(key, "==$", 3) != 0)
 500  624                  return;
 501      -        param = strtol(value + 3, NULL, 10);
      625 +        param = strtol(key + 3, NULL, 10);
 502  626          if (!get_param(param, &size_name, &size_sym))
 503  627                  return;
 504  628          array_expr = symbol_expression(array_sym);
 505  629          size_expr = symbol_expression(size_sym);
      630 +        limit_type = strtol(value, NULL, 10);
 506  631  
 507      -        tmp = set_state_expr(size_id, array_expr, alloc_expr_state(size_expr));
      632 +        tmp = set_state_expr(size_id, array_expr, alloc_compare_size(limit_type, size_expr));
 508  633          if (!tmp)
 509  634                  return;
 510      -        set_state_expr(link_id, size_expr, alloc_expr_state(array_expr));
      635 +        set_state_expr(link_id, size_expr, alloc_state_expr(array_expr));
 511  636  }
 512  637  
 513      -static void set_arraysize_arg(const char *array_name, struct symbol *array_sym, char *key, char *value)
      638 +static void set_implied(struct expression *call, struct expression *array_expr, char *key, char *value)
 514  639  {
 515      -        struct expression *array_expr;
 516  640          struct expression *size_expr;
 517  641          struct symbol *size_sym;
 518  642          char *size_name;
 519  643          long param;
 520  644          struct sm_state *tmp;
      645 +        int limit_type;
 521  646  
 522      -        param = strtol(key, NULL, 10);
      647 +        if (strncmp(key, "==$", 3) != 0)
      648 +                return;
      649 +        param = strtol(key + 3, NULL, 10);
 523  650          if (!get_param(param, &size_name, &size_sym))
 524  651                  return;
 525      -        array_expr = symbol_expression(array_sym);
 526  652          size_expr = symbol_expression(size_sym);
 527  653  
 528      -        tmp = set_state_expr(size_id, array_expr, alloc_expr_state(size_expr));
      654 +        limit_type = strtol(value, NULL, 10);
      655 +        tmp = set_state_expr(size_id, array_expr, alloc_compare_size(limit_type, size_expr));
 529  656          if (!tmp)
 530  657                  return;
 531      -        set_state_expr(link_id, size_expr, alloc_expr_state(array_expr));
      658 +        set_state_expr(link_id, size_expr, alloc_state_expr(array_expr));
 532  659  }
 533  660  
 534  661  static void munge_start_states(struct statement *stmt)
 535  662  {
 536  663          struct state_list *slist = NULL;
 537  664          struct sm_state *sm;
 538  665          struct sm_state *poss;
 539  666  
 540  667          FOR_EACH_MY_SM(size_id, __get_cur_stree(), sm) {
 541  668                  if (sm->state != &merged)
↓ open down ↓ 11 lines elided ↑ open up ↑
 553  680                  } END_FOR_EACH_PTR(poss);
 554  681          } END_FOR_EACH_SM(sm);
 555  682  
 556  683          FOR_EACH_PTR(slist, sm) {
 557  684                  set_state(size_id, sm->name, sm->sym, sm->state);
 558  685          } END_FOR_EACH_PTR(sm);
 559  686  
 560  687          free_slist(&slist);
 561  688  }
 562  689  
      690 +static void set_used(struct expression *expr)
      691 +{
      692 +        struct expression *parent;
      693 +        struct expression *array;
      694 +        struct expression *offset;
      695 +        struct sm_state *tmp;
      696 +        int limit_type;
      697 +
      698 +        if (expr->op != SPECIAL_INCREMENT)
      699 +                return;
      700 +
      701 +        limit_type = USED_LAST;
      702 +        if (expr->type == EXPR_POSTOP)
      703 +                limit_type = USED_COUNT;
      704 +
      705 +        parent = expr_get_parent_expr(expr);
      706 +        if (!parent || parent->type != EXPR_BINOP)
      707 +                return;
      708 +        parent = expr_get_parent_expr(parent);
      709 +        if (!parent || !is_array(parent))
      710 +                return;
      711 +
      712 +        array = get_array_base(parent);
      713 +        offset = get_array_offset(parent);
      714 +        if (offset != expr)
      715 +                return;
      716 +
      717 +        tmp = set_state_expr(size_id, array, alloc_compare_size(limit_type, offset->unop));
      718 +        if (!tmp)
      719 +                return;
      720 +        set_state_expr(link_id, offset->unop, alloc_state_expr(array));
      721 +}
      722 +
      723 +static int match_assign_array(struct expression *expr)
      724 +{
      725 +        // FIXME: implement
      726 +        return 0;
      727 +}
      728 +
      729 +static int match_assign_size(struct expression *expr)
      730 +{
      731 +        struct expression *right, *size, *array;
      732 +        struct smatch_state *state;
      733 +        struct sm_state *tmp;
      734 +        int limit_type;
      735 +
      736 +        right = expr->right;
      737 +        size = right;
      738 +        if (size->type == EXPR_BINOP)
      739 +                size = size->left;
      740 +
      741 +        array = get_array_variable(size);
      742 +        if (!array)
      743 +                return 0;
      744 +        state = get_state_expr(size_id, array);
      745 +        if (!state || !state->data)
      746 +                return 0;
      747 +
      748 +        limit_type = state_to_limit(state);
      749 +        if (limit_type < 0)
      750 +                return 0;
      751 +
      752 +        if (right->type == EXPR_BINOP && !match_size_binop(size, right, &limit_type))
      753 +                return 0;
      754 +
      755 +        tmp = set_state_expr(size_id, array, alloc_compare_size(limit_type, expr->left));
      756 +        if (!tmp)
      757 +                return 0;
      758 +        set_state_expr(link_id, expr->left, alloc_state_expr(array));
      759 +        return 1;
      760 +}
      761 +
      762 +static void match_assign(struct expression *expr)
      763 +{
      764 +        if (expr->op != '=')
      765 +                return;
      766 +
      767 +        if (match_assign_array(expr))
      768 +                return;
      769 +        match_assign_size(expr);
      770 +}
      771 +
      772 +static void match_copy(const char *fn, struct expression *expr, void *unused)
      773 +{
      774 +        struct expression *src, *size;
      775 +        int src_param, size_param;
      776 +
      777 +        src = get_argument_from_call_expr(expr->args, 1);
      778 +        size = get_argument_from_call_expr(expr->args, 2);
      779 +        src = strip_expr(src);
      780 +        size = strip_expr(size);
      781 +        if (!src || !size)
      782 +                return;
      783 +        if (src->type != EXPR_SYMBOL || size->type != EXPR_SYMBOL)
      784 +                return;
      785 +
      786 +        src_param = get_param_num_from_sym(src->symbol);
      787 +        size_param = get_param_num_from_sym(size->symbol);
      788 +        if (src_param < 0 || size_param < 0)
      789 +                return;
      790 +
      791 +        sql_insert_cache(call_implies, "'%s', '%s', 0, %d, %d, %d, '==$%d', '%d'",
      792 +                         get_base_file(), get_function(), fn_static(),
      793 +                         BYTE_COUNT, src_param, size_param, BYTE_COUNT);
      794 +}
      795 +
 563  796  void register_buf_comparison(int id)
 564  797  {
      798 +        int i;
      799 +
 565  800          size_id = id;
 566  801  
      802 +        set_dynamic_states(size_id);
      803 +
 567  804          add_unmatched_state_hook(size_id, &unmatched_state);
 568  805  
 569  806          add_allocation_function("malloc", &match_alloc, 0);
 570  807          add_allocation_function("memdup", &match_alloc, 1);
 571  808          add_allocation_function("realloc", &match_alloc, 1);
 572  809          if (option_project == PROJ_KERNEL) {
 573  810                  add_allocation_function("kmalloc", &match_alloc, 0);
 574  811                  add_allocation_function("kzalloc", &match_alloc, 0);
 575  812                  add_allocation_function("vmalloc", &match_alloc, 0);
 576  813                  add_allocation_function("__vmalloc", &match_alloc, 0);
↓ open down ↓ 2 lines elided ↑ open up ↑
 579  816                  add_allocation_function("kmemdup_user", &match_alloc, 1);
 580  817                  add_allocation_function("dma_alloc_attrs", &match_alloc, 1);
 581  818                  add_allocation_function("pci_alloc_consistent", &match_alloc, 1);
 582  819                  add_allocation_function("pci_alloc_coherent", &match_alloc, 1);
 583  820                  add_allocation_function("devm_kmalloc", &match_alloc, 1);
 584  821                  add_allocation_function("devm_kzalloc", &match_alloc, 1);
 585  822                  add_allocation_function("kcalloc", &match_calloc, 0);
 586  823                  add_allocation_function("devm_kcalloc", &match_calloc, 1);
 587  824                  add_allocation_function("kmalloc_array", &match_calloc, 0);
 588  825                  add_allocation_function("krealloc", &match_alloc, 1);
      826 +
      827 +                add_function_hook("copy_from_user", &match_copy, NULL);
      828 +                add_function_hook("__copy_from_user", &match_copy, NULL);
 589  829          }
 590  830  
 591  831          add_hook(&array_check, OP_HOOK);
 592  832          add_hook(&array_check_data_info, OP_HOOK);
      833 +        add_hook(&set_used, OP_HOOK);
 593  834  
 594  835          add_hook(&match_call, FUNCTION_CALL_HOOK);
 595      -        select_caller_info_hook(set_param_compare, ARRAY_LEN);
 596      -        select_caller_info_hook(set_arraysize_arg, ARRAYSIZE_ARG);
 597  836          add_hook(&munge_start_states, AFTER_DEF_HOOK);
      837 +
      838 +        add_hook(&match_assign, ASSIGNMENT_HOOK);
      839 +
      840 +        for (i = BYTE_COUNT; i <= USED_COUNT; i++) {
      841 +                select_call_implies_hook(i, &set_implied);
      842 +                select_caller_info_hook(set_param_compare, i);
      843 +                select_return_implies_hook(i, &set_implied);
      844 +        }
 598  845  }
 599  846  
 600  847  void register_buf_comparison_links(int id)
 601  848  {
 602  849          link_id = id;
      850 +        set_dynamic_states(link_id);
 603  851          add_merge_hook(link_id, &merge_links);
 604  852          add_modification_hook(link_id, &match_link_modify);
 605  853  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX