Print this page
11972 resync smatch

Split Close
Expand all
Collapse all
          --- old/usr/src/tools/smatch/src/smatch_extra.c
          +++ new/usr/src/tools/smatch/src/smatch_extra.c
↓ open down ↓ 91 lines elided ↑ open up ↑
  92   92  void call_extra_mod_hooks(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
  93   93  {
  94   94          call_extra_hooks(extra_mod_hooks, name, sym, expr, state);
  95   95  }
  96   96  
  97   97  void call_extra_nomod_hooks(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
  98   98  {
  99   99          call_extra_hooks(extra_nomod_hooks, name, sym, expr, state);
 100  100  }
 101  101  
      102 +static void set_union_info(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
      103 +{
      104 +        struct symbol *type, *tmp, *inner_type, *inner, *new_type;
      105 +        struct expression *deref, *member_expr;
      106 +        struct smatch_state *new;
      107 +        int offset, inner_offset;
      108 +        static bool in_recurse;
      109 +        char *member_name;
      110 +
      111 +        if (__in_fake_assign)
      112 +                return;
      113 +
      114 +        if (in_recurse)
      115 +                return;
      116 +        in_recurse = true;
      117 +
      118 +        if (!expr || expr->type != EXPR_DEREF || !expr->member)
      119 +                goto done;
      120 +        offset = get_member_offset_from_deref(expr);
      121 +        if (offset < 0)
      122 +                goto done;
      123 +
      124 +        deref = strip_expr(expr->deref);
      125 +        type = get_type(deref);
      126 +        if (type_is_ptr(type))
      127 +                type = get_real_base_type(type);
      128 +        if (!type || type->type != SYM_STRUCT)
      129 +                goto done;
      130 +
      131 +        FOR_EACH_PTR(type->symbol_list, tmp) {
      132 +                inner_type = get_real_base_type(tmp);
      133 +                if (!inner_type || inner_type->type != SYM_UNION)
      134 +                        continue;
      135 +
      136 +                inner = first_ptr_list((struct ptr_list *)inner_type->symbol_list);
      137 +                if (!inner || !inner->ident)
      138 +                        continue;
      139 +
      140 +                inner_offset = get_member_offset(type, inner->ident->name);
      141 +                if (inner_offset < offset)
      142 +                        continue;
      143 +                if (inner_offset > offset)
      144 +                        goto done;
      145 +
      146 +                FOR_EACH_PTR(inner_type->symbol_list, inner) {
      147 +                        struct symbol *tmp_type;
      148 +
      149 +                        if (!inner->ident || inner->ident == expr->member)
      150 +                                continue;
      151 +                        tmp_type = get_real_base_type(inner);
      152 +                        if (tmp_type && tmp_type->type == SYM_STRUCT)
      153 +                                continue;
      154 +                        member_expr = deref;
      155 +                        if (tmp->ident)
      156 +                                member_expr = member_expression(member_expr, '.', tmp->ident);
      157 +                        member_expr = member_expression(member_expr, expr->op, inner->ident);
      158 +                        member_name = expr_to_var(member_expr);
      159 +                        if (!member_name)
      160 +                                continue;
      161 +                        new_type = get_real_base_type(inner);
      162 +                        new = alloc_estate_rl(cast_rl(new_type, estate_rl(state)));
      163 +                        set_extra_mod_helper(member_name, sym, member_expr, new);
      164 +                        free_string(member_name);
      165 +                } END_FOR_EACH_PTR(inner);
      166 +        } END_FOR_EACH_PTR(tmp);
      167 +
      168 +done:
      169 +        in_recurse = false;
      170 +}
      171 +
 102  172  static bool in_param_set;
 103  173  void set_extra_mod_helper(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
 104  174  {
      175 +        if (!expr)
      176 +                expr = gen_expression_from_name_sym(name, sym);
 105  177          remove_from_equiv(name, sym);
      178 +        set_union_info(name, sym, expr, state);
 106  179          call_extra_mod_hooks(name, sym, expr, state);
 107      -        if ((__in_fake_assign || in_param_set) &&
      180 +        update_mtag_data(expr, state);
      181 +        if (in_param_set &&
 108  182              estate_is_unknown(state) && !get_state(SMATCH_EXTRA, name, sym))
 109  183                  return;
 110  184          set_state(SMATCH_EXTRA, name, sym, state);
 111  185  }
 112  186  
 113  187  static void set_extra_nomod_helper(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
 114  188  {
 115  189          call_extra_nomod_hooks(name, sym, expr, state);
 116  190          set_state(SMATCH_EXTRA, name, sym, state);
 117  191  }
↓ open down ↓ 47 lines elided ↑ open up ↑
 165  239  
 166  240          snprintf(buf, sizeof(buf), "%s->%s", orig_name, name + len);
 167  241          ret = alloc_string(buf);
 168  242          free_string(orig_name);
 169  243          return ret;
 170  244  free:
 171  245          free_string(orig_name);
 172  246          return NULL;
 173  247  }
 174  248  
 175      -static char *get_long_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym)
      249 +static char *get_long_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym, bool use_stack)
 176  250  {
 177  251          struct expression *tmp;
 178  252          struct sm_state *sm;
 179  253          char buf[256];
 180  254  
 181  255          /*
 182  256           * Just prepend the name with a different name/sym and return that.
 183  257           * For example, if we set "foo->bar = bar;" then we clamp "bar->baz",
 184  258           * that also clamps "foo->bar->baz".
 185  259           *
↓ open down ↓ 3 lines elided ↑ open up ↑
 189  263                  tmp = sm->state->data;
 190  264                  if (!tmp || tmp->type != EXPR_SYMBOL)
 191  265                          continue;
 192  266                  if (tmp->symbol == sym)
 193  267                          goto found;
 194  268          } END_FOR_EACH_SM(sm);
 195  269  
 196  270          return NULL;
 197  271  
 198  272  found:
      273 +        if (!use_stack && name[tmp->symbol->ident->len] != '-')
      274 +                return NULL;
 199  275          snprintf(buf, sizeof(buf), "%s%s", sm->name, name + tmp->symbol->ident->len);
 200  276          *new_sym = sm->sym;
 201  277          return alloc_string(buf);
 202  278  }
 203  279  
 204  280  char *get_other_name_sym_helper(const char *name, struct symbol *sym, struct symbol **new_sym, bool use_stack)
 205  281  {
 206  282          char buf[256];
 207  283          char *ret;
 208  284          int len;
↓ open down ↓ 8 lines elided ↑ open up ↑
 217  293                  return ret;
 218  294  
 219  295          ret = map_long_to_short_name_sym(name, sym, new_sym, use_stack);
 220  296          if (ret)
 221  297                  return ret;
 222  298  
 223  299          len = snprintf(buf, sizeof(buf), "%s", name);
 224  300          if (len >= sizeof(buf) - 2)
 225  301                  return NULL;
 226  302  
 227      -        while (len >= 1) {
      303 +        while (use_stack && len >= 1) {
 228  304                  if (buf[len] == '>' && buf[len - 1] == '-') {
 229  305                          len--;
 230  306                          buf[len] = '\0';
 231  307                          ret = get_other_name_sym_from_chunk(name, buf, len + 2, sym, new_sym);
 232  308                          if (ret)
 233  309                                  return ret;
 234  310                  }
 235  311                  len--;
 236  312          }
 237  313  
 238      -        ret = get_long_name_sym(name, sym, new_sym);
      314 +        ret = get_long_name_sym(name, sym, new_sym, use_stack);
 239  315          if (ret)
 240  316                  return ret;
 241  317  
 242  318          return NULL;
 243  319  }
 244  320  
 245  321  char *get_other_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym)
 246  322  {
 247  323          return get_other_name_sym_helper(name, sym, new_sym, true);
 248  324  }
↓ open down ↓ 2 lines elided ↑ open up ↑
 251  327  {
 252  328          return get_other_name_sym_helper(name, sym, new_sym, false);
 253  329  }
 254  330  
 255  331  void set_extra_mod(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
 256  332  {
 257  333          char *new_name;
 258  334          struct symbol *new_sym;
 259  335  
 260  336          set_extra_mod_helper(name, sym, expr, state);
 261      -        new_name = get_other_name_sym(name, sym, &new_sym);
      337 +        new_name = get_other_name_sym_nostack(name, sym, &new_sym);
 262  338          if (new_name && new_sym)
 263      -                set_extra_mod_helper(new_name, new_sym, expr, state);
      339 +                set_extra_mod_helper(new_name, new_sym, NULL, state);
 264  340          free_string(new_name);
 265  341  }
 266  342  
 267  343  static struct expression *chunk_get_array_base(struct expression *expr)
 268  344  {
 269  345          /*
 270  346           * The problem with is_array() is that it only returns true for things
 271  347           * like foo[1] but not for foo[1].bar.
 272  348           *
 273  349           */
↓ open down ↓ 950 lines elided ↑ open up ↑
1224 1300          default:
1225 1301                  return;
1226 1302          }
1227 1303  }
1228 1304  
1229 1305  static void asm_expr(struct statement *stmt)
1230 1306  {
1231 1307  
1232 1308          struct expression *expr;
1233 1309          struct symbol *type;
1234      -        int state = 0;
1235 1310  
1236 1311          FOR_EACH_PTR(stmt->asm_outputs, expr) {
1237      -                switch (state) {
1238      -                case 0: /* identifier */
1239      -                case 1: /* constraint */
1240      -                        state++;
     1312 +                if (expr->type != EXPR_ASM_OPERAND) {
     1313 +                        sm_perror("unexpected asm param type %d", expr->type);
1241 1314                          continue;
1242      -                case 2: /* expression */
1243      -                        state = 0;
1244      -                        type = get_type(strip_expr(expr));
1245      -                        set_extra_expr_mod(expr, alloc_estate_whole(type));
1246      -                        continue;
1247 1315                  }
     1316 +                type = get_type(strip_expr(expr->expr));
     1317 +                set_extra_expr_mod(expr->expr, alloc_estate_whole(type));
1248 1318          } END_FOR_EACH_PTR(expr);
1249 1319  }
1250 1320  
1251 1321  static void check_dereference(struct expression *expr)
1252 1322  {
1253 1323          struct smatch_state *state;
1254 1324  
1255 1325          if (__in_fake_assign)
1256 1326                  return;
1257 1327          if (outside_of_function())
↓ open down ↓ 15 lines elided ↑ open up ↑
1273 1343                          rl = clone_rl(valid_ptr_rl);
1274 1344  
1275 1345                  set_extra_expr_nomod(expr, alloc_estate_rl(rl));
1276 1346          }
1277 1347  }
1278 1348  
1279 1349  static void match_dereferences(struct expression *expr)
1280 1350  {
1281 1351          if (expr->type != EXPR_PREOP)
1282 1352                  return;
     1353 +        if (getting_address(expr))
     1354 +                return;
1283 1355          /* it's saying that foo[1] = bar dereferences foo[1] */
1284 1356          if (is_array(expr))
1285 1357                  return;
1286 1358          check_dereference(expr->unop);
1287 1359  }
1288 1360  
1289 1361  static void match_pointer_as_array(struct expression *expr)
1290 1362  {
1291 1363          if (!is_array(expr))
1292 1364                  return;
↓ open down ↓ 903 lines elided ↑ open up ↑
2196 2268          char *start;
2197 2269          char *end;
2198 2270          struct smatch_state *state;
2199 2271  
2200 2272          strncpy(buf, name, sizeof(buf) - 1);
2201 2273          buf[sizeof(buf) - 1] = '\0';
2202 2274  
2203 2275          start = &buf[0];
2204 2276          while (*start == '*') {
2205 2277                  start++;
2206      -                state = get_state(SMATCH_EXTRA, start, sym);
     2278 +                state = __get_state(SMATCH_EXTRA, start, sym);
2207 2279                  if (!state)
2208 2280                          continue;
2209 2281                  if (!estate_rl(state))
2210 2282                          return 1;
2211 2283                  if (estate_min(state).value == 0 &&
2212 2284                      estate_max(state).value == 0)
2213 2285                          return 1;
2214 2286          }
2215 2287  
2216 2288          start = &buf[0];
↓ open down ↓ 149 lines elided ↑ open up ↑
2366 2438  
2367 2439          abs_rl = cast_rl(rl_type(start), estate_rl(state));
2368 2440          return rl_intersection(abs_rl, start);
2369 2441  }
2370 2442  
2371 2443  static void struct_member_callback(struct expression *call, int param, char *printed_name, struct sm_state *sm)
2372 2444  {
2373 2445          struct range_list *rl;
2374 2446          sval_t dummy;
2375 2447  
2376      -        if (estate_is_whole(sm->state))
     2448 +        if (estate_is_whole(sm->state) || !estate_rl(sm->state))
2377 2449                  return;
2378 2450          if (filter_unused_param_value_info(call, param, printed_name, sm))
2379 2451                  return;
2380 2452          rl = estate_rl(sm->state);
2381 2453          rl = intersect_with_real_abs_var_sym(sm->name, sm->sym, rl);
     2454 +        if (!rl)
     2455 +                return;
2382 2456          sql_insert_caller_info(call, PARAM_VALUE, param, printed_name, show_rl(rl));
2383 2457          if (!estate_get_single_value(sm->state, &dummy)) {
2384 2458                  if (estate_has_hard_max(sm->state))
2385 2459                          sql_insert_caller_info(call, HARD_MAX, param, printed_name,
2386 2460                                                 sval_to_str(estate_max(sm->state)));
2387 2461                  if (estate_has_fuzzy_max(sm->state))
2388 2462                          sql_insert_caller_info(call, FUZZY_MAX, param, printed_name,
2389 2463                                                 sval_to_str(estate_get_fuzzy_max(sm->state)));
2390 2464          }
2391 2465  }
↓ open down ↓ 170 lines elided ↑ open up ↑
2562 2636          db_param_limit_filter(expr, param, key, value, PARAM_LIMIT);
2563 2637  }
2564 2638  
2565 2639  static void db_param_filter(struct expression *expr, int param, char *key, char *value)
2566 2640  {
2567 2641          db_param_limit_filter(expr, param, key, value, PARAM_FILTER);
2568 2642  }
2569 2643  
2570 2644  static void db_param_add_set(struct expression *expr, int param, char *key, char *value, enum info_type op)
2571 2645  {
2572      -        struct expression *arg;
     2646 +        struct expression *arg, *gen_expr;
2573 2647          char *name;
2574 2648          char *other_name = NULL;
2575 2649          struct symbol *sym, *other_sym;
2576 2650          struct symbol *param_type, *arg_type;
2577 2651          struct smatch_state *state;
2578 2652          struct range_list *new = NULL;
2579 2653          struct range_list *added = NULL;
2580 2654  
2581 2655          while (expr->type == EXPR_ASSIGNMENT)
2582 2656                  expr = strip_expr(expr->right);
2583 2657          if (expr->type != EXPR_CALL)
2584 2658                  return;
2585 2659  
2586 2660          arg = get_argument_from_call_expr(expr->args, param);
2587 2661          if (!arg)
2588 2662                  return;
2589 2663  
2590 2664          arg_type = get_arg_type_from_key(expr->fn, param, arg, key);
2591 2665          param_type = get_member_type_from_key(arg, key);
     2666 +        if (param_type && param_type->type == SYM_STRUCT)
     2667 +                return;
2592 2668          name = get_variable_from_key(arg, key, &sym);
2593 2669          if (!name || !sym)
2594 2670                  goto free;
     2671 +        gen_expr = gen_expression_from_key(arg, key);
2595 2672  
2596 2673          state = get_state(SMATCH_EXTRA, name, sym);
2597 2674          if (state)
2598 2675                  new = estate_rl(state);
2599 2676  
2600 2677          call_results_to_rl(expr, arg_type, value, &added);
2601 2678          added = cast_rl(param_type, added);
2602 2679          if (op == PARAM_SET)
2603 2680                  new = added;
2604 2681          else
2605 2682                  new = rl_union(new, added);
2606 2683  
2607 2684          other_name = get_other_name_sym_nostack(name, sym, &other_sym);
2608      -        set_extra_mod(name, sym, NULL, alloc_estate_rl(new));
     2685 +        set_extra_mod(name, sym, gen_expr, alloc_estate_rl(new));
2609 2686          if (other_name && other_sym)
2610      -                set_extra_mod(other_name, other_sym, NULL, alloc_estate_rl(new));
     2687 +                set_extra_mod(other_name, other_sym, gen_expr, alloc_estate_rl(new));
2611 2688  free:
2612 2689          free_string(other_name);
2613 2690          free_string(name);
2614 2691  }
2615 2692  
2616 2693  static void db_param_add(struct expression *expr, int param, char *key, char *value)
2617 2694  {
2618 2695          in_param_set = true;
2619 2696          db_param_add_set(expr, param, key, value, PARAM_ADD);
2620 2697          in_param_set = false;
↓ open down ↓ 249 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX