Print this page
new smatch

Split Close
Expand all
Collapse all
          --- old/usr/src/tools/smatch/src/smatch_db.c
          +++ new/usr/src/tools/smatch/src/smatch_db.c
↓ open down ↓ 500 lines elided ↑ open up ↑
 501  501          if (expr->type != EXPR_SYMBOL)
 502  502                  return 0;
 503  503          if (expr->symbol->ctype.modifiers & (MOD_NONLOCAL | MOD_STATIC | MOD_ADDRESSABLE))
 504  504                  return 0;
 505  505          return 1;
 506  506  }
 507  507  
 508  508  void sql_select_return_states(const char *cols, struct expression *call,
 509  509          int (*callback)(void*, int, char**, char**), void *info)
 510  510  {
      511 +        struct expression *fn;
 511  512          int row_count = 0;
 512  513  
 513  514          if (is_fake_call(call))
 514  515                  return;
 515  516  
 516      -        if (call->fn->type != EXPR_SYMBOL || !call->fn->symbol || is_local_symbol(call->fn)) {
      517 +        fn = strip_expr(call->fn);
      518 +        if (fn->type != EXPR_SYMBOL || !fn->symbol || is_local_symbol(fn)) {
 517  519                  sql_select_return_states_pointer(cols, call, callback, info);
 518  520                  return;
 519  521          }
 520  522  
 521      -        if (inlinable(call->fn)) {
      523 +        if (inlinable(fn)) {
 522  524                  mem_sql(callback, info,
 523  525                          "select %s from return_states where call_id = '%lu' order by return_id, type;",
 524  526                          cols, (unsigned long)call);
 525  527                  return;
 526  528          }
 527  529  
 528  530          run_sql(get_row_count, &row_count, "select count(*) from return_states where %s;",
 529      -                get_static_filter(call->fn->symbol));
      531 +                get_static_filter(fn->symbol));
 530  532          if (row_count > 3000)
 531  533                  return;
 532  534  
 533  535          run_sql(callback, info, "select %s from return_states where %s order by file, return_id, type;",
 534      -                cols, get_static_filter(call->fn->symbol));
      536 +                cols, get_static_filter(fn->symbol));
 535  537  }
 536  538  
 537  539  #define CALL_IMPLIES 0
 538  540  #define RETURN_IMPLIES 1
 539  541  
 540  542  struct implies_info {
 541  543          int type;
 542  544          struct db_implies_cb_list *cb_list;
 543  545          struct expression *expr;
 544  546          struct symbol *sym;
↓ open down ↓ 166 lines elided ↑ open up ↑
 711  713          ret_info.static_returns_call = NULL;
 712  714          ret_info.return_type = &llong_ctype;
 713  715          ret_info.return_range_list = NULL;
 714  716  
 715  717          run_sql(db_return_callback, &ret_info,
 716  718                  "select distinct return from return_states where function = '%s';",
 717  719                  fn_name);
 718  720          return ret_info.return_range_list;
 719  721  }
 720  722  
      723 +/*
      724 + * This is used when we have a function that takes a function pointer as a
      725 + * parameter.  "frob(blah, blah, my_function);"  We know that the return values
      726 + * from frob() come from my_funcion() so we want to find the possible returns
      727 + * of my_function(), but we don't know which arguments are passed to it.
      728 + *
      729 + */
      730 +struct range_list *db_return_vals_no_args(struct expression *expr)
      731 +{
      732 +        struct return_info ret_info = {};
      733 +
      734 +        if (!expr || expr->type != EXPR_SYMBOL)
      735 +                return NULL;
      736 +
      737 +        ret_info.static_returns_call = expr;
      738 +        ret_info.return_type = get_type(expr);
      739 +        ret_info.return_type = get_real_base_type(ret_info.return_type);
      740 +        if (!ret_info.return_type)
      741 +                return NULL;
      742 +
      743 +        run_sql(db_return_callback, &ret_info,
      744 +                "select distinct return from return_states where %s;",
      745 +                get_static_filter(expr->symbol));
      746 +
      747 +        return ret_info.return_range_list;
      748 +}
      749 +
 721  750  static void match_call_marker(struct expression *expr)
 722  751  {
 723  752          struct symbol *type;
 724  753  
 725  754          type = get_type(expr->fn);
 726  755          if (type && type->type == SYM_PTR)
 727  756                  type = get_real_base_type(type);
 728  757  
 729  758          /*
 730  759           * we just want to record something in the database so that if we have
↓ open down ↓ 368 lines elided ↑ open up ↑
1099 1128                  char *ptr;
1100 1129  
1101 1130                  if (sym->ctype.modifiers & MOD_STATIC)
1102 1131                          get_ptr_names(get_base_file(), sym->ident->name);
1103 1132                  else
1104 1133                          get_ptr_names(NULL, sym->ident->name);
1105 1134  
1106 1135                  if (ptr_list_size((struct ptr_list *)ptr_names) > 20) {
1107 1136                          __free_ptr_list((struct ptr_list **)&ptr_names);
1108 1137                          __free_ptr_list((struct ptr_list **)&ptr_names_done);
1109      -                        stree = __pop_fake_cur_stree();
1110      -                        free_stree(&stree);
     1138 +                        __free_fake_cur_stree();
1111 1139                          return;
1112 1140                  }
1113 1141  
1114 1142                  sql_select_caller_info(&data,
1115 1143                                         "call_id, type, parameter, key, value",
1116 1144                                         sym);
1117 1145  
1118 1146  
1119 1147                  stree = __pop_fake_cur_stree();
1120 1148                  if (!data.ignore)
1121 1149                          merge_stree(&data.final_states, stree);
1122 1150                  free_stree(&stree);
1123 1151                  __push_fake_cur_stree();
1124 1152                  __unnullify_path();
1125 1153                  data.prev_func_id = -1;
1126 1154                  data.ignore = 0;
     1155 +                data.results = 0;
1127 1156  
1128 1157                  FOR_EACH_PTR(ptr_names, ptr) {
1129 1158                          run_sql(caller_info_callback, &data,
1130 1159                                  "select call_id, type, parameter, key, value"
1131 1160                                  " from common_caller_info where function = '%s' order by call_id",
1132 1161                                  ptr);
1133 1162                  } END_FOR_EACH_PTR(ptr);
1134 1163  
1135 1164                  if (data.results) {
1136 1165                          FOR_EACH_PTR(ptr_names, ptr) {
↓ open down ↓ 117 lines elided ↑ open up ↑
1254 1283          };
1255 1284  
1256 1285          if (!sym || !sym->ident)
1257 1286                  return;
1258 1287  
1259 1288          info.sym = sym;
1260 1289          sql_select_implies("function, type, parameter, key, value", &info,
1261 1290                             call_implies_callbacks);
1262 1291  }
1263 1292  
     1293 +static char *get_fn_param_str(struct expression *expr)
     1294 +{
     1295 +        struct expression *tmp;
     1296 +        int param;
     1297 +        char buf[32];
     1298 +
     1299 +        tmp = get_assigned_expr(expr);
     1300 +        if (tmp)
     1301 +                expr = tmp;
     1302 +        expr = strip_expr(expr);
     1303 +        if (!expr || expr->type != EXPR_CALL)
     1304 +                return NULL;
     1305 +        expr = strip_expr(expr->fn);
     1306 +        if (!expr || expr->type != EXPR_SYMBOL)
     1307 +                return NULL;
     1308 +        param = get_param_num(expr);
     1309 +        if (param < 0)
     1310 +                return NULL;
     1311 +
     1312 +        snprintf(buf, sizeof(buf), "[r $%d]", param);
     1313 +        return alloc_sname(buf);
     1314 +}
     1315 +
1264 1316  static char *get_return_compare_is_param(struct expression *expr)
1265 1317  {
1266 1318          char *var;
1267 1319          char buf[256];
1268 1320          int comparison;
1269 1321          int param;
1270 1322  
1271 1323          param = get_param_num(expr);
1272 1324          if (param < 0)
1273 1325                  return NULL;
↓ open down ↓ 25 lines elided ↑ open up ↑
1299 1351                  return compare_str;
1300 1352  
1301 1353          return expr_param_comparison(expr, -1);
1302 1354  }
1303 1355  
1304 1356  static const char *get_return_ranges_str(struct expression *expr, struct range_list **rl_p)
1305 1357  {
1306 1358          struct range_list *rl;
1307 1359          char *return_ranges;
1308 1360          sval_t sval;
     1361 +        char *fn_param_str;
1309 1362          char *compare_str;
1310 1363          char *math_str;
1311 1364          char buf[128];
1312 1365  
1313 1366          *rl_p = NULL;
1314 1367  
1315 1368          if (!expr)
1316 1369                  return alloc_sname("");
1317 1370  
1318 1371          if (get_implied_value(expr, &sval)) {
1319 1372                  sval = sval_cast(cur_func_return_type(), sval);
1320 1373                  *rl_p = alloc_rl(sval, sval);
1321 1374                  return sval_to_str_or_err_ptr(sval);
1322 1375          }
1323 1376  
     1377 +        fn_param_str = get_fn_param_str(expr);
1324 1378          compare_str = expr_equal_to_param(expr, -1);
1325 1379          math_str = get_value_in_terms_of_parameter_math(expr);
1326 1380  
1327 1381          if (get_implied_rl(expr, &rl) && !is_whole_rl(rl)) {
1328 1382                  rl = cast_rl(cur_func_return_type(), rl);
1329 1383                  return_ranges = show_rl(rl);
1330 1384          } else if (get_imaginary_absolute(expr, &rl)){
1331 1385                  rl = cast_rl(cur_func_return_type(), rl);
1332 1386                  return alloc_sname(show_rl(rl));
1333 1387          } else {
1334 1388                  get_absolute_rl(expr, &rl);
1335 1389                  rl = cast_rl(cur_func_return_type(), rl);
1336 1390                  return_ranges = show_rl(rl);
1337 1391          }
1338 1392          *rl_p = rl;
1339 1393  
     1394 +        if (fn_param_str) {
     1395 +                snprintf(buf, sizeof(buf), "%s%s", return_ranges, fn_param_str);
     1396 +                return alloc_sname(buf);
     1397 +        }
1340 1398          if (compare_str) {
1341 1399                  snprintf(buf, sizeof(buf), "%s%s", return_ranges, compare_str);
1342 1400                  return alloc_sname(buf);
1343 1401          }
1344 1402          if (math_str) {
1345 1403                  snprintf(buf, sizeof(buf), "%s[%s]", return_ranges, math_str);
1346 1404                  return alloc_sname(buf);
1347 1405          }
1348 1406          compare_str = get_return_compare_str(expr);
1349 1407          if (compare_str) {
↓ open down ↓ 494 lines elided ↑ open up ↑
1844 1902  }
1845 1903  
1846 1904  static int split_on_bool_sm(struct sm_state *sm, struct expression *expr)
1847 1905  {
1848 1906          struct returned_state_callback *cb;
1849 1907          struct range_list *ret_rl;
1850 1908          const char *return_ranges;
1851 1909          struct sm_state *tmp;
1852 1910          int ret = 0;
1853 1911          int nr_possible, nr_states;
1854      -        char *compare_str = NULL;
1855      -        char buf[128];
1856 1912          struct state_list *already_handled = NULL;
1857 1913  
1858 1914          if (!sm || !sm->merged)
1859 1915                  return 0;
1860 1916  
1861 1917          if (too_many_possible(sm))
1862 1918                  return 0;
1863 1919  
1864 1920          /* bail if it gets too complicated */
1865 1921          nr_possible = ptr_list_size((struct ptr_list *)sm->possible);
↓ open down ↓ 8 lines elided ↑ open up ↑
1874 1930                          continue;
1875 1931                  add_ptr_list(&already_handled, tmp);
1876 1932  
1877 1933                  ret = 1;
1878 1934                  __push_fake_cur_stree();
1879 1935  
1880 1936                  overwrite_states_using_pool(sm, tmp);
1881 1937  
1882 1938                  return_ranges = get_return_ranges_str(expr, &ret_rl);
1883 1939                  set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));
1884      -                compare_str = get_return_compare_str(expr);
1885      -                if (compare_str) {
1886      -                        snprintf(buf, sizeof(buf), "%s%s", return_ranges, compare_str);
1887      -                        return_ranges = alloc_sname(buf);
1888      -                }
1889      -
1890 1940                  return_id++;
1891 1941                  FOR_EACH_PTR(returned_state_callbacks, cb) {
1892 1942                          cb->callback(return_id, (char *)return_ranges, expr);
1893 1943                  } END_FOR_EACH_PTR(cb);
1894 1944  
1895 1945                  __free_fake_cur_stree();
1896 1946          } END_FOR_EACH_PTR(tmp);
1897 1947  
1898 1948          free_slist(&already_handled);
1899 1949  
↓ open down ↓ 107 lines elided ↑ open up ↑
2007 2057          }
2008 2058  
2009 2059  vanilla:
2010 2060          return_ranges = get_return_ranges_str(expr, &ret_rl);
2011 2061          set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));
2012 2062  
2013 2063          return_id++;
2014 2064          nr_states = get_db_state_count();
2015 2065          if (nr_states >= 10000) {
2016 2066                  match_return_info(return_id, (char *)return_ranges, expr);
     2067 +                print_limited_param_set(return_id, (char *)return_ranges, expr);
2017 2068                  mark_all_params_untracked(return_id, (char *)return_ranges, expr);
2018 2069                  return;
2019 2070          }
2020 2071          FOR_EACH_PTR(returned_state_callbacks, cb) {
2021 2072                  cb->callback(return_id, (char *)return_ranges, expr);
2022 2073          } END_FOR_EACH_PTR(cb);
2023 2074  }
2024 2075  
2025 2076  static void print_returned_struct_members(int return_id, char *return_ranges, struct expression *expr)
2026 2077  {
↓ open down ↓ 253 lines elided ↑ open up ↑
2280 2331                  token = token->next;
2281 2332          }
2282 2333          clear_token_alloc();
2283 2334  }
2284 2335  
2285 2336  static char *get_next_string(char **str)
2286 2337  {
2287 2338          static char string[256];
2288 2339          char *start;
2289 2340          char *p = *str;
2290      -        int len;
     2341 +        int len, i, j;
2291 2342  
2292 2343          if (*p == '\0')
2293 2344                  return NULL;
2294 2345          start = p;
2295 2346  
2296      -        while (*p != '\0' && *p != ' ' && *p != '\n')
     2347 +        while (*p != '\0' && *p != '\n') {
     2348 +                if (*p == '\\' && *(p + 1) == ' ') {
     2349 +                        p += 2;
     2350 +                        continue;
     2351 +                }
     2352 +                if (*p == ' ')
     2353 +                        break;
2297 2354                  p++;
     2355 +        }
2298 2356  
2299 2357          len = p - start;
2300      -        if (len > 256) {
2301      -                memcpy(string, start, 255);
2302      -                string[255] = '\0';
     2358 +        if (len >= sizeof(string)) {
     2359 +                memcpy(string, start, sizeof(string));
     2360 +                string[sizeof(string) - 1] = '\0';
2303 2361                  sm_ierror("return_fix: '%s' too long", string);
2304 2362                  **str = '\0';
2305 2363                  return NULL;
2306 2364          }
2307 2365          memcpy(string, start, len);
2308 2366          string[len] = '\0';
     2367 +        for (i = 0; i < sizeof(string) - 1; i++) {
     2368 +                if (string[i] == '\\' && string[i + 1] == ' ') {
     2369 +                        for (j = i; string[j] != '\0'; j++)
     2370 +                                string[j] = string[j + 1];
     2371 +                }
     2372 +        }
2309 2373          if (*p != '\0')
2310 2374                  p++;
2311 2375          *str = p;
2312 2376          return string;
2313 2377  }
2314 2378  
2315 2379  static void register_return_replacements(void)
2316 2380  {
2317 2381          char *func, *orig, *new;
2318 2382          char filename[256];
↓ open down ↓ 173 lines elided ↑ open up ↑
2492 2556  
2493 2557          name_len = strlen(param_name);
2494 2558  
2495 2559          if (state_name[0] == '*') {
2496 2560                  add_star = true;
2497 2561                  state_name++;
2498 2562          }
2499 2563  
2500 2564          if (strcmp(state_name, param_name) == 0) {
2501 2565                  snprintf(buf, sizeof(buf), "%s$", add_star ? "*" : "");
2502      -                return buf;
     2566 +                return alloc_sname(buf);
2503 2567          }
2504 2568  
2505 2569          if (state_name[name_len] == '-' && /* check for '-' from "->" */
2506 2570              strncmp(state_name, param_name, name_len) == 0) {
2507 2571                  snprintf(buf, sizeof(buf), "%s$%s",
2508 2572                           add_star ? "*" : "", state_name + name_len);
2509      -                return buf;
     2573 +                return alloc_sname(buf);
2510 2574          }
2511 2575          return NULL;
2512 2576  }
2513 2577  
2514 2578  const char *get_param_name_var_sym(const char *name, struct symbol *sym)
2515 2579  {
2516 2580          if (!sym || !sym->ident)
2517 2581                  return NULL;
2518 2582  
2519 2583          return state_name_to_param_name(name, sym->ident->name);
↓ open down ↓ 83 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX