Print this page
11972 resync smatch


  82 
  83 void call_extra_hooks(struct void_fn_list *hooks, const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
  84 {
  85         mod_hook **fn;
  86 
  87         FOR_EACH_PTR(hooks, fn) {
  88                 (*fn)(name, sym, expr, state);
  89         } END_FOR_EACH_PTR(fn);
  90 }
  91 
  92 void call_extra_mod_hooks(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
  93 {
  94         call_extra_hooks(extra_mod_hooks, name, sym, expr, state);
  95 }
  96 
  97 void call_extra_nomod_hooks(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
  98 {
  99         call_extra_hooks(extra_nomod_hooks, name, sym, expr, state);
 100 }
 101 






































































 102 static bool in_param_set;
 103 void set_extra_mod_helper(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
 104 {


 105         remove_from_equiv(name, sym);

 106         call_extra_mod_hooks(name, sym, expr, state);
 107         if ((__in_fake_assign || in_param_set) &&

 108             estate_is_unknown(state) && !get_state(SMATCH_EXTRA, name, sym))
 109                 return;
 110         set_state(SMATCH_EXTRA, name, sym, state);
 111 }
 112 
 113 static void set_extra_nomod_helper(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
 114 {
 115         call_extra_nomod_hooks(name, sym, expr, state);
 116         set_state(SMATCH_EXTRA, name, sym, state);
 117 }
 118 
 119 static char *get_pointed_at(const char *name, struct symbol *sym, struct symbol **new_sym)
 120 {
 121         struct expression *assigned;
 122 
 123         if (name[0] != '*')
 124                 return NULL;
 125         if (strcmp(name + 1, sym->ident->name) != 0)
 126                 return NULL;
 127 


 155 
 156                 snprintf(buf, sizeof(buf), "%s.%s", orig_name + 1, name + len);
 157                 ret = alloc_string(buf);
 158                 free_string(orig_name);
 159                 return ret;
 160         }
 161 
 162         orig_name = expr_to_var_sym(assigned, new_sym);
 163         if (!orig_name || !*new_sym)
 164                 goto free;
 165 
 166         snprintf(buf, sizeof(buf), "%s->%s", orig_name, name + len);
 167         ret = alloc_string(buf);
 168         free_string(orig_name);
 169         return ret;
 170 free:
 171         free_string(orig_name);
 172         return NULL;
 173 }
 174 
 175 static char *get_long_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym)
 176 {
 177         struct expression *tmp;
 178         struct sm_state *sm;
 179         char buf[256];
 180 
 181         /*
 182          * Just prepend the name with a different name/sym and return that.
 183          * For example, if we set "foo->bar = bar;" then we clamp "bar->baz",
 184          * that also clamps "foo->bar->baz".
 185          *
 186          */
 187 
 188         FOR_EACH_MY_SM(check_assigned_expr_id, __get_cur_stree(), sm) {
 189                 tmp = sm->state->data;
 190                 if (!tmp || tmp->type != EXPR_SYMBOL)
 191                         continue;
 192                 if (tmp->symbol == sym)
 193                         goto found;
 194         } END_FOR_EACH_SM(sm);
 195 
 196         return NULL;
 197 
 198 found:


 199         snprintf(buf, sizeof(buf), "%s%s", sm->name, name + tmp->symbol->ident->len);
 200         *new_sym = sm->sym;
 201         return alloc_string(buf);
 202 }
 203 
 204 char *get_other_name_sym_helper(const char *name, struct symbol *sym, struct symbol **new_sym, bool use_stack)
 205 {
 206         char buf[256];
 207         char *ret;
 208         int len;
 209 
 210         *new_sym = NULL;
 211 
 212         if (!sym || !sym->ident)
 213                 return NULL;
 214 
 215         ret = get_pointed_at(name, sym, new_sym);
 216         if (ret)
 217                 return ret;
 218 
 219         ret = map_long_to_short_name_sym(name, sym, new_sym, use_stack);
 220         if (ret)
 221                 return ret;
 222 
 223         len = snprintf(buf, sizeof(buf), "%s", name);
 224         if (len >= sizeof(buf) - 2)
 225                 return NULL;
 226 
 227         while (len >= 1) {
 228                 if (buf[len] == '>' && buf[len - 1] == '-') {
 229                         len--;
 230                         buf[len] = '\0';
 231                         ret = get_other_name_sym_from_chunk(name, buf, len + 2, sym, new_sym);
 232                         if (ret)
 233                                 return ret;
 234                 }
 235                 len--;
 236         }
 237 
 238         ret = get_long_name_sym(name, sym, new_sym);
 239         if (ret)
 240                 return ret;
 241 
 242         return NULL;
 243 }
 244 
 245 char *get_other_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym)
 246 {
 247         return get_other_name_sym_helper(name, sym, new_sym, true);
 248 }
 249 
 250 char *get_other_name_sym_nostack(const char *name, struct symbol *sym, struct symbol **new_sym)
 251 {
 252         return get_other_name_sym_helper(name, sym, new_sym, false);
 253 }
 254 
 255 void set_extra_mod(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
 256 {
 257         char *new_name;
 258         struct symbol *new_sym;
 259 
 260         set_extra_mod_helper(name, sym, expr, state);
 261         new_name = get_other_name_sym(name, sym, &new_sym);
 262         if (new_name && new_sym)
 263                 set_extra_mod_helper(new_name, new_sym, expr, state);
 264         free_string(new_name);
 265 }
 266 
 267 static struct expression *chunk_get_array_base(struct expression *expr)
 268 {
 269         /*
 270          * The problem with is_array() is that it only returns true for things
 271          * like foo[1] but not for foo[1].bar.
 272          *
 273          */
 274         expr = strip_expr(expr);
 275         while (expr && expr->type == EXPR_DEREF)
 276                 expr = strip_expr(expr->deref);
 277         return get_array_base(expr);
 278 }
 279 
 280 static int chunk_has_array(struct expression *expr)
 281 {
 282         return !!chunk_get_array_base(expr);
 283 }


1214                 clear_pointed_at_state(expr->unop);
1215                 break;
1216         case SPECIAL_DECREMENT:
1217                 state = get_state_expr(SMATCH_EXTRA, expr->unop);
1218                 state = decrement_state(state);
1219                 if (!state)
1220                         state = alloc_estate_whole(get_type(expr));
1221                 set_extra_expr_mod(expr->unop, state);
1222                 clear_pointed_at_state(expr->unop);
1223                 break;
1224         default:
1225                 return;
1226         }
1227 }
1228 
1229 static void asm_expr(struct statement *stmt)
1230 {
1231 
1232         struct expression *expr;
1233         struct symbol *type;
1234         int state = 0;
1235 
1236         FOR_EACH_PTR(stmt->asm_outputs, expr) {
1237                 switch (state) {
1238                 case 0: /* identifier */
1239                 case 1: /* constraint */
1240                         state++;
1241                         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                 }


1248         } END_FOR_EACH_PTR(expr);
1249 }
1250 
1251 static void check_dereference(struct expression *expr)
1252 {
1253         struct smatch_state *state;
1254 
1255         if (__in_fake_assign)
1256                 return;
1257         if (outside_of_function())
1258                 return;
1259         state = get_extra_state(expr);
1260         if (state) {
1261                 struct range_list *rl;
1262 
1263                 rl = rl_intersection(estate_rl(state), valid_ptr_rl);
1264                 if (rl_equiv(rl, estate_rl(state)))
1265                         return;
1266                 set_extra_expr_nomod(expr, alloc_estate_rl(rl));
1267         } else {
1268                 struct range_list *rl;
1269 
1270                 if (get_mtag_rl(expr, &rl))
1271                         rl = rl_intersection(rl, valid_ptr_rl);
1272                 else
1273                         rl = clone_rl(valid_ptr_rl);
1274 
1275                 set_extra_expr_nomod(expr, alloc_estate_rl(rl));
1276         }
1277 }
1278 
1279 static void match_dereferences(struct expression *expr)
1280 {
1281         if (expr->type != EXPR_PREOP)
1282                 return;


1283         /* it's saying that foo[1] = bar dereferences foo[1] */
1284         if (is_array(expr))
1285                 return;
1286         check_dereference(expr->unop);
1287 }
1288 
1289 static void match_pointer_as_array(struct expression *expr)
1290 {
1291         if (!is_array(expr))
1292                 return;
1293         check_dereference(get_array_base(expr));
1294 }
1295 
1296 static void find_dereferences(struct expression *expr)
1297 {
1298         while (expr->type == EXPR_PREOP) {
1299                 if (expr->op == '*')
1300                         check_dereference(expr->unop);
1301                 expr = strip_expr(expr->unop);
1302         }


2186         if (!estate)
2187                 return 0;
2188         if (!rl_has_sval(estate_rl(estate), sval_type_val(estate_type(estate), 0)))
2189                 return 1;
2190         return 0;
2191 }
2192 
2193 int parent_is_null_var_sym(const char *name, struct symbol *sym)
2194 {
2195         char buf[256];
2196         char *start;
2197         char *end;
2198         struct smatch_state *state;
2199 
2200         strncpy(buf, name, sizeof(buf) - 1);
2201         buf[sizeof(buf) - 1] = '\0';
2202 
2203         start = &buf[0];
2204         while (*start == '*') {
2205                 start++;
2206                 state = get_state(SMATCH_EXTRA, start, sym);
2207                 if (!state)
2208                         continue;
2209                 if (!estate_rl(state))
2210                         return 1;
2211                 if (estate_min(state).value == 0 &&
2212                     estate_max(state).value == 0)
2213                         return 1;
2214         }
2215 
2216         start = &buf[0];
2217         while (*start == '&')
2218                 start++;
2219 
2220         while ((end = strrchr(start, '-'))) {
2221                 *end = '\0';
2222                 state = __get_state(SMATCH_EXTRA, start, sym);
2223                 if (!state)
2224                         continue;
2225                 if (estate_min(state).value == 0 &&
2226                     estate_max(state).value == 0)


2356 }
2357 
2358 struct range_list *intersect_with_real_abs_expr(struct expression *expr, struct range_list *start)
2359 {
2360         struct smatch_state *state;
2361         struct range_list *abs_rl;
2362 
2363         state = get_real_absolute_state(expr);
2364         if (!state || !estate_rl(state))
2365                 return start;
2366 
2367         abs_rl = cast_rl(rl_type(start), estate_rl(state));
2368         return rl_intersection(abs_rl, start);
2369 }
2370 
2371 static void struct_member_callback(struct expression *call, int param, char *printed_name, struct sm_state *sm)
2372 {
2373         struct range_list *rl;
2374         sval_t dummy;
2375 
2376         if (estate_is_whole(sm->state))
2377                 return;
2378         if (filter_unused_param_value_info(call, param, printed_name, sm))
2379                 return;
2380         rl = estate_rl(sm->state);
2381         rl = intersect_with_real_abs_var_sym(sm->name, sm->sym, rl);


2382         sql_insert_caller_info(call, PARAM_VALUE, param, printed_name, show_rl(rl));
2383         if (!estate_get_single_value(sm->state, &dummy)) {
2384                 if (estate_has_hard_max(sm->state))
2385                         sql_insert_caller_info(call, HARD_MAX, param, printed_name,
2386                                                sval_to_str(estate_max(sm->state)));
2387                 if (estate_has_fuzzy_max(sm->state))
2388                         sql_insert_caller_info(call, FUZZY_MAX, param, printed_name,
2389                                                sval_to_str(estate_get_fuzzy_max(sm->state)));
2390         }
2391 }
2392 
2393 static void returned_struct_members(int return_id, char *return_ranges, struct expression *expr)
2394 {
2395         struct symbol *returned_sym;
2396         char *returned_name;
2397         struct sm_state *sm;
2398         char *compare_str;
2399         char name_buf[256];
2400         char val_buf[256];
2401         int len;


2552         }
2553 
2554         if (op == PARAM_LIMIT && arg->type == EXPR_BINOP)
2555                 db_param_limit_binops(arg, key, new);
2556 free:
2557         free_string(name);
2558 }
2559 
2560 static void db_param_limit(struct expression *expr, int param, char *key, char *value)
2561 {
2562         db_param_limit_filter(expr, param, key, value, PARAM_LIMIT);
2563 }
2564 
2565 static void db_param_filter(struct expression *expr, int param, char *key, char *value)
2566 {
2567         db_param_limit_filter(expr, param, key, value, PARAM_FILTER);
2568 }
2569 
2570 static void db_param_add_set(struct expression *expr, int param, char *key, char *value, enum info_type op)
2571 {
2572         struct expression *arg;
2573         char *name;
2574         char *other_name = NULL;
2575         struct symbol *sym, *other_sym;
2576         struct symbol *param_type, *arg_type;
2577         struct smatch_state *state;
2578         struct range_list *new = NULL;
2579         struct range_list *added = NULL;
2580 
2581         while (expr->type == EXPR_ASSIGNMENT)
2582                 expr = strip_expr(expr->right);
2583         if (expr->type != EXPR_CALL)
2584                 return;
2585 
2586         arg = get_argument_from_call_expr(expr->args, param);
2587         if (!arg)
2588                 return;
2589 
2590         arg_type = get_arg_type_from_key(expr->fn, param, arg, key);
2591         param_type = get_member_type_from_key(arg, key);


2592         name = get_variable_from_key(arg, key, &sym);
2593         if (!name || !sym)
2594                 goto free;

2595 
2596         state = get_state(SMATCH_EXTRA, name, sym);
2597         if (state)
2598                 new = estate_rl(state);
2599 
2600         call_results_to_rl(expr, arg_type, value, &added);
2601         added = cast_rl(param_type, added);
2602         if (op == PARAM_SET)
2603                 new = added;
2604         else
2605                 new = rl_union(new, added);
2606 
2607         other_name = get_other_name_sym_nostack(name, sym, &other_sym);
2608         set_extra_mod(name, sym, NULL, alloc_estate_rl(new));
2609         if (other_name && other_sym)
2610                 set_extra_mod(other_name, other_sym, NULL, alloc_estate_rl(new));
2611 free:
2612         free_string(other_name);
2613         free_string(name);
2614 }
2615 
2616 static void db_param_add(struct expression *expr, int param, char *key, char *value)
2617 {
2618         in_param_set = true;
2619         db_param_add_set(expr, param, key, value, PARAM_ADD);
2620         in_param_set = false;
2621 }
2622 
2623 static void db_param_set(struct expression *expr, int param, char *key, char *value)
2624 {
2625         in_param_set = true;
2626         db_param_add_set(expr, param, key, value, PARAM_SET);
2627         in_param_set = false;
2628 }
2629 
2630 static void match_lost_param(struct expression *call, int param)




  82 
  83 void call_extra_hooks(struct void_fn_list *hooks, const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
  84 {
  85         mod_hook **fn;
  86 
  87         FOR_EACH_PTR(hooks, fn) {
  88                 (*fn)(name, sym, expr, state);
  89         } END_FOR_EACH_PTR(fn);
  90 }
  91 
  92 void call_extra_mod_hooks(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
  93 {
  94         call_extra_hooks(extra_mod_hooks, name, sym, expr, state);
  95 }
  96 
  97 void call_extra_nomod_hooks(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
  98 {
  99         call_extra_hooks(extra_nomod_hooks, name, sym, expr, state);
 100 }
 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 
 172 static bool in_param_set;
 173 void set_extra_mod_helper(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
 174 {
 175         if (!expr)
 176                 expr = gen_expression_from_name_sym(name, sym);
 177         remove_from_equiv(name, sym);
 178         set_union_info(name, sym, expr, state);
 179         call_extra_mod_hooks(name, sym, expr, state);
 180         update_mtag_data(expr, state);
 181         if (in_param_set &&
 182             estate_is_unknown(state) && !get_state(SMATCH_EXTRA, name, sym))
 183                 return;
 184         set_state(SMATCH_EXTRA, name, sym, state);
 185 }
 186 
 187 static void set_extra_nomod_helper(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
 188 {
 189         call_extra_nomod_hooks(name, sym, expr, state);
 190         set_state(SMATCH_EXTRA, name, sym, state);
 191 }
 192 
 193 static char *get_pointed_at(const char *name, struct symbol *sym, struct symbol **new_sym)
 194 {
 195         struct expression *assigned;
 196 
 197         if (name[0] != '*')
 198                 return NULL;
 199         if (strcmp(name + 1, sym->ident->name) != 0)
 200                 return NULL;
 201 


 229 
 230                 snprintf(buf, sizeof(buf), "%s.%s", orig_name + 1, name + len);
 231                 ret = alloc_string(buf);
 232                 free_string(orig_name);
 233                 return ret;
 234         }
 235 
 236         orig_name = expr_to_var_sym(assigned, new_sym);
 237         if (!orig_name || !*new_sym)
 238                 goto free;
 239 
 240         snprintf(buf, sizeof(buf), "%s->%s", orig_name, name + len);
 241         ret = alloc_string(buf);
 242         free_string(orig_name);
 243         return ret;
 244 free:
 245         free_string(orig_name);
 246         return NULL;
 247 }
 248 
 249 static char *get_long_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym, bool use_stack)
 250 {
 251         struct expression *tmp;
 252         struct sm_state *sm;
 253         char buf[256];
 254 
 255         /*
 256          * Just prepend the name with a different name/sym and return that.
 257          * For example, if we set "foo->bar = bar;" then we clamp "bar->baz",
 258          * that also clamps "foo->bar->baz".
 259          *
 260          */
 261 
 262         FOR_EACH_MY_SM(check_assigned_expr_id, __get_cur_stree(), sm) {
 263                 tmp = sm->state->data;
 264                 if (!tmp || tmp->type != EXPR_SYMBOL)
 265                         continue;
 266                 if (tmp->symbol == sym)
 267                         goto found;
 268         } END_FOR_EACH_SM(sm);
 269 
 270         return NULL;
 271 
 272 found:
 273         if (!use_stack && name[tmp->symbol->ident->len] != '-')
 274                 return NULL;
 275         snprintf(buf, sizeof(buf), "%s%s", sm->name, name + tmp->symbol->ident->len);
 276         *new_sym = sm->sym;
 277         return alloc_string(buf);
 278 }
 279 
 280 char *get_other_name_sym_helper(const char *name, struct symbol *sym, struct symbol **new_sym, bool use_stack)
 281 {
 282         char buf[256];
 283         char *ret;
 284         int len;
 285 
 286         *new_sym = NULL;
 287 
 288         if (!sym || !sym->ident)
 289                 return NULL;
 290 
 291         ret = get_pointed_at(name, sym, new_sym);
 292         if (ret)
 293                 return ret;
 294 
 295         ret = map_long_to_short_name_sym(name, sym, new_sym, use_stack);
 296         if (ret)
 297                 return ret;
 298 
 299         len = snprintf(buf, sizeof(buf), "%s", name);
 300         if (len >= sizeof(buf) - 2)
 301                 return NULL;
 302 
 303         while (use_stack && len >= 1) {
 304                 if (buf[len] == '>' && buf[len - 1] == '-') {
 305                         len--;
 306                         buf[len] = '\0';
 307                         ret = get_other_name_sym_from_chunk(name, buf, len + 2, sym, new_sym);
 308                         if (ret)
 309                                 return ret;
 310                 }
 311                 len--;
 312         }
 313 
 314         ret = get_long_name_sym(name, sym, new_sym, use_stack);
 315         if (ret)
 316                 return ret;
 317 
 318         return NULL;
 319 }
 320 
 321 char *get_other_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym)
 322 {
 323         return get_other_name_sym_helper(name, sym, new_sym, true);
 324 }
 325 
 326 char *get_other_name_sym_nostack(const char *name, struct symbol *sym, struct symbol **new_sym)
 327 {
 328         return get_other_name_sym_helper(name, sym, new_sym, false);
 329 }
 330 
 331 void set_extra_mod(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
 332 {
 333         char *new_name;
 334         struct symbol *new_sym;
 335 
 336         set_extra_mod_helper(name, sym, expr, state);
 337         new_name = get_other_name_sym_nostack(name, sym, &new_sym);
 338         if (new_name && new_sym)
 339                 set_extra_mod_helper(new_name, new_sym, NULL, state);
 340         free_string(new_name);
 341 }
 342 
 343 static struct expression *chunk_get_array_base(struct expression *expr)
 344 {
 345         /*
 346          * The problem with is_array() is that it only returns true for things
 347          * like foo[1] but not for foo[1].bar.
 348          *
 349          */
 350         expr = strip_expr(expr);
 351         while (expr && expr->type == EXPR_DEREF)
 352                 expr = strip_expr(expr->deref);
 353         return get_array_base(expr);
 354 }
 355 
 356 static int chunk_has_array(struct expression *expr)
 357 {
 358         return !!chunk_get_array_base(expr);
 359 }


1290                 clear_pointed_at_state(expr->unop);
1291                 break;
1292         case SPECIAL_DECREMENT:
1293                 state = get_state_expr(SMATCH_EXTRA, expr->unop);
1294                 state = decrement_state(state);
1295                 if (!state)
1296                         state = alloc_estate_whole(get_type(expr));
1297                 set_extra_expr_mod(expr->unop, state);
1298                 clear_pointed_at_state(expr->unop);
1299                 break;
1300         default:
1301                 return;
1302         }
1303 }
1304 
1305 static void asm_expr(struct statement *stmt)
1306 {
1307 
1308         struct expression *expr;
1309         struct symbol *type;

1310 
1311         FOR_EACH_PTR(stmt->asm_outputs, expr) {
1312                 if (expr->type != EXPR_ASM_OPERAND) {
1313                         sm_perror("unexpected asm param type %d", expr->type);


1314                         continue;





1315                 }
1316                 type = get_type(strip_expr(expr->expr));
1317                 set_extra_expr_mod(expr->expr, alloc_estate_whole(type));
1318         } END_FOR_EACH_PTR(expr);
1319 }
1320 
1321 static void check_dereference(struct expression *expr)
1322 {
1323         struct smatch_state *state;
1324 
1325         if (__in_fake_assign)
1326                 return;
1327         if (outside_of_function())
1328                 return;
1329         state = get_extra_state(expr);
1330         if (state) {
1331                 struct range_list *rl;
1332 
1333                 rl = rl_intersection(estate_rl(state), valid_ptr_rl);
1334                 if (rl_equiv(rl, estate_rl(state)))
1335                         return;
1336                 set_extra_expr_nomod(expr, alloc_estate_rl(rl));
1337         } else {
1338                 struct range_list *rl;
1339 
1340                 if (get_mtag_rl(expr, &rl))
1341                         rl = rl_intersection(rl, valid_ptr_rl);
1342                 else
1343                         rl = clone_rl(valid_ptr_rl);
1344 
1345                 set_extra_expr_nomod(expr, alloc_estate_rl(rl));
1346         }
1347 }
1348 
1349 static void match_dereferences(struct expression *expr)
1350 {
1351         if (expr->type != EXPR_PREOP)
1352                 return;
1353         if (getting_address(expr))
1354                 return;
1355         /* it's saying that foo[1] = bar dereferences foo[1] */
1356         if (is_array(expr))
1357                 return;
1358         check_dereference(expr->unop);
1359 }
1360 
1361 static void match_pointer_as_array(struct expression *expr)
1362 {
1363         if (!is_array(expr))
1364                 return;
1365         check_dereference(get_array_base(expr));
1366 }
1367 
1368 static void find_dereferences(struct expression *expr)
1369 {
1370         while (expr->type == EXPR_PREOP) {
1371                 if (expr->op == '*')
1372                         check_dereference(expr->unop);
1373                 expr = strip_expr(expr->unop);
1374         }


2258         if (!estate)
2259                 return 0;
2260         if (!rl_has_sval(estate_rl(estate), sval_type_val(estate_type(estate), 0)))
2261                 return 1;
2262         return 0;
2263 }
2264 
2265 int parent_is_null_var_sym(const char *name, struct symbol *sym)
2266 {
2267         char buf[256];
2268         char *start;
2269         char *end;
2270         struct smatch_state *state;
2271 
2272         strncpy(buf, name, sizeof(buf) - 1);
2273         buf[sizeof(buf) - 1] = '\0';
2274 
2275         start = &buf[0];
2276         while (*start == '*') {
2277                 start++;
2278                 state = __get_state(SMATCH_EXTRA, start, sym);
2279                 if (!state)
2280                         continue;
2281                 if (!estate_rl(state))
2282                         return 1;
2283                 if (estate_min(state).value == 0 &&
2284                     estate_max(state).value == 0)
2285                         return 1;
2286         }
2287 
2288         start = &buf[0];
2289         while (*start == '&')
2290                 start++;
2291 
2292         while ((end = strrchr(start, '-'))) {
2293                 *end = '\0';
2294                 state = __get_state(SMATCH_EXTRA, start, sym);
2295                 if (!state)
2296                         continue;
2297                 if (estate_min(state).value == 0 &&
2298                     estate_max(state).value == 0)


2428 }
2429 
2430 struct range_list *intersect_with_real_abs_expr(struct expression *expr, struct range_list *start)
2431 {
2432         struct smatch_state *state;
2433         struct range_list *abs_rl;
2434 
2435         state = get_real_absolute_state(expr);
2436         if (!state || !estate_rl(state))
2437                 return start;
2438 
2439         abs_rl = cast_rl(rl_type(start), estate_rl(state));
2440         return rl_intersection(abs_rl, start);
2441 }
2442 
2443 static void struct_member_callback(struct expression *call, int param, char *printed_name, struct sm_state *sm)
2444 {
2445         struct range_list *rl;
2446         sval_t dummy;
2447 
2448         if (estate_is_whole(sm->state) || !estate_rl(sm->state))
2449                 return;
2450         if (filter_unused_param_value_info(call, param, printed_name, sm))
2451                 return;
2452         rl = estate_rl(sm->state);
2453         rl = intersect_with_real_abs_var_sym(sm->name, sm->sym, rl);
2454         if (!rl)
2455                 return;
2456         sql_insert_caller_info(call, PARAM_VALUE, param, printed_name, show_rl(rl));
2457         if (!estate_get_single_value(sm->state, &dummy)) {
2458                 if (estate_has_hard_max(sm->state))
2459                         sql_insert_caller_info(call, HARD_MAX, param, printed_name,
2460                                                sval_to_str(estate_max(sm->state)));
2461                 if (estate_has_fuzzy_max(sm->state))
2462                         sql_insert_caller_info(call, FUZZY_MAX, param, printed_name,
2463                                                sval_to_str(estate_get_fuzzy_max(sm->state)));
2464         }
2465 }
2466 
2467 static void returned_struct_members(int return_id, char *return_ranges, struct expression *expr)
2468 {
2469         struct symbol *returned_sym;
2470         char *returned_name;
2471         struct sm_state *sm;
2472         char *compare_str;
2473         char name_buf[256];
2474         char val_buf[256];
2475         int len;


2626         }
2627 
2628         if (op == PARAM_LIMIT && arg->type == EXPR_BINOP)
2629                 db_param_limit_binops(arg, key, new);
2630 free:
2631         free_string(name);
2632 }
2633 
2634 static void db_param_limit(struct expression *expr, int param, char *key, char *value)
2635 {
2636         db_param_limit_filter(expr, param, key, value, PARAM_LIMIT);
2637 }
2638 
2639 static void db_param_filter(struct expression *expr, int param, char *key, char *value)
2640 {
2641         db_param_limit_filter(expr, param, key, value, PARAM_FILTER);
2642 }
2643 
2644 static void db_param_add_set(struct expression *expr, int param, char *key, char *value, enum info_type op)
2645 {
2646         struct expression *arg, *gen_expr;
2647         char *name;
2648         char *other_name = NULL;
2649         struct symbol *sym, *other_sym;
2650         struct symbol *param_type, *arg_type;
2651         struct smatch_state *state;
2652         struct range_list *new = NULL;
2653         struct range_list *added = NULL;
2654 
2655         while (expr->type == EXPR_ASSIGNMENT)
2656                 expr = strip_expr(expr->right);
2657         if (expr->type != EXPR_CALL)
2658                 return;
2659 
2660         arg = get_argument_from_call_expr(expr->args, param);
2661         if (!arg)
2662                 return;
2663 
2664         arg_type = get_arg_type_from_key(expr->fn, param, arg, key);
2665         param_type = get_member_type_from_key(arg, key);
2666         if (param_type && param_type->type == SYM_STRUCT)
2667                 return;
2668         name = get_variable_from_key(arg, key, &sym);
2669         if (!name || !sym)
2670                 goto free;
2671         gen_expr = gen_expression_from_key(arg, key);
2672 
2673         state = get_state(SMATCH_EXTRA, name, sym);
2674         if (state)
2675                 new = estate_rl(state);
2676 
2677         call_results_to_rl(expr, arg_type, value, &added);
2678         added = cast_rl(param_type, added);
2679         if (op == PARAM_SET)
2680                 new = added;
2681         else
2682                 new = rl_union(new, added);
2683 
2684         other_name = get_other_name_sym_nostack(name, sym, &other_sym);
2685         set_extra_mod(name, sym, gen_expr, alloc_estate_rl(new));
2686         if (other_name && other_sym)
2687                 set_extra_mod(other_name, other_sym, gen_expr, alloc_estate_rl(new));
2688 free:
2689         free_string(other_name);
2690         free_string(name);
2691 }
2692 
2693 static void db_param_add(struct expression *expr, int param, char *key, char *value)
2694 {
2695         in_param_set = true;
2696         db_param_add_set(expr, param, key, value, PARAM_ADD);
2697         in_param_set = false;
2698 }
2699 
2700 static void db_param_set(struct expression *expr, int param, char *key, char *value)
2701 {
2702         in_param_set = true;
2703         db_param_add_set(expr, param, key, value, PARAM_SET);
2704         in_param_set = false;
2705 }
2706 
2707 static void match_lost_param(struct expression *call, int param)