Print this page
new smatch


 491         run_sql(callback, info,
 492                 "select %s from return_states join function_ptr where "
 493                 "return_states.function == function_ptr.function and ptr = '%s' "
 494                 "and searchable = 1 "
 495                 "order by function_ptr.file, return_states.file, return_id, type;",
 496                 cols, ptr);
 497 }
 498 
 499 static int is_local_symbol(struct expression *expr)
 500 {
 501         if (expr->type != EXPR_SYMBOL)
 502                 return 0;
 503         if (expr->symbol->ctype.modifiers & (MOD_NONLOCAL | MOD_STATIC | MOD_ADDRESSABLE))
 504                 return 0;
 505         return 1;
 506 }
 507 
 508 void sql_select_return_states(const char *cols, struct expression *call,
 509         int (*callback)(void*, int, char**, char**), void *info)
 510 {

 511         int row_count = 0;
 512 
 513         if (is_fake_call(call))
 514                 return;
 515 
 516         if (call->fn->type != EXPR_SYMBOL || !call->fn->symbol || is_local_symbol(call->fn)) {

 517                 sql_select_return_states_pointer(cols, call, callback, info);
 518                 return;
 519         }
 520 
 521         if (inlinable(call->fn)) {
 522                 mem_sql(callback, info,
 523                         "select %s from return_states where call_id = '%lu' order by return_id, type;",
 524                         cols, (unsigned long)call);
 525                 return;
 526         }
 527 
 528         run_sql(get_row_count, &row_count, "select count(*) from return_states where %s;",
 529                 get_static_filter(call->fn->symbol));
 530         if (row_count > 3000)
 531                 return;
 532 
 533         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));
 535 }
 536 
 537 #define CALL_IMPLIES 0
 538 #define RETURN_IMPLIES 1
 539 
 540 struct implies_info {
 541         int type;
 542         struct db_implies_cb_list *cb_list;
 543         struct expression *expr;
 544         struct symbol *sym;
 545 };
 546 
 547 void sql_select_implies(const char *cols, struct implies_info *info,
 548         int (*callback)(void*, int, char**, char**))
 549 {
 550         if (info->type == RETURN_IMPLIES && inlinable(info->expr->fn)) {
 551                 mem_sql(callback, info,
 552                         "select %s from return_implies where call_id = '%lu';",
 553                         cols, (unsigned long)info->expr);
 554                 return;


 701                         "select distinct return from return_states where %s;",
 702                         get_static_filter(expr->fn->symbol));
 703         }
 704         return ret_info.return_range_list;
 705 }
 706 
 707 struct range_list *db_return_vals_from_str(const char *fn_name)
 708 {
 709         struct return_info ret_info;
 710 
 711         ret_info.static_returns_call = NULL;
 712         ret_info.return_type = &llong_ctype;
 713         ret_info.return_range_list = NULL;
 714 
 715         run_sql(db_return_callback, &ret_info,
 716                 "select distinct return from return_states where function = '%s';",
 717                 fn_name);
 718         return ret_info.return_range_list;
 719 }
 720 



























 721 static void match_call_marker(struct expression *expr)
 722 {
 723         struct symbol *type;
 724 
 725         type = get_type(expr->fn);
 726         if (type && type->type == SYM_PTR)
 727                 type = get_real_base_type(type);
 728 
 729         /*
 730          * we just want to record something in the database so that if we have
 731          * two calls like:  frob(4); frob(some_unkown); then on the receiving
 732          * side we know that sometimes frob is called with unknown parameters.
 733          */
 734 
 735         sql_insert_caller_info(expr, INTERNAL, -1, "%call_marker%", type_to_str(type));
 736 }
 737 
 738 static char *show_offset(int offset)
 739 {
 740         static char buf[64];


1089 
1090         if (!sym || !sym->ident)
1091                 return;
1092 
1093         gettimeofday(&data.start_time, NULL);
1094 
1095         __push_fake_cur_stree();
1096         __unnullify_path();
1097 
1098         if (!__inline_fn) {
1099                 char *ptr;
1100 
1101                 if (sym->ctype.modifiers & MOD_STATIC)
1102                         get_ptr_names(get_base_file(), sym->ident->name);
1103                 else
1104                         get_ptr_names(NULL, sym->ident->name);
1105 
1106                 if (ptr_list_size((struct ptr_list *)ptr_names) > 20) {
1107                         __free_ptr_list((struct ptr_list **)&ptr_names);
1108                         __free_ptr_list((struct ptr_list **)&ptr_names_done);
1109                         stree = __pop_fake_cur_stree();
1110                         free_stree(&stree);
1111                         return;
1112                 }
1113 
1114                 sql_select_caller_info(&data,
1115                                        "call_id, type, parameter, key, value",
1116                                        sym);
1117 
1118 
1119                 stree = __pop_fake_cur_stree();
1120                 if (!data.ignore)
1121                         merge_stree(&data.final_states, stree);
1122                 free_stree(&stree);
1123                 __push_fake_cur_stree();
1124                 __unnullify_path();
1125                 data.prev_func_id = -1;
1126                 data.ignore = 0;

1127 
1128                 FOR_EACH_PTR(ptr_names, ptr) {
1129                         run_sql(caller_info_callback, &data,
1130                                 "select call_id, type, parameter, key, value"
1131                                 " from common_caller_info where function = '%s' order by call_id",
1132                                 ptr);
1133                 } END_FOR_EACH_PTR(ptr);
1134 
1135                 if (data.results) {
1136                         FOR_EACH_PTR(ptr_names, ptr) {
1137                                 free_string(ptr);
1138                         } END_FOR_EACH_PTR(ptr);
1139                         goto free_ptr_names;
1140                 }
1141 
1142                 FOR_EACH_PTR(ptr_names, ptr) {
1143                         run_sql(caller_info_callback, &data,
1144                                 "select call_id, type, parameter, key, value"
1145                                 " from caller_info where function = '%s' order by call_id",
1146                                 ptr);


1244         info.sym = expr->fn->symbol;
1245         sql_select_implies("function, type, parameter, key, value", &info,
1246                            return_implies_callbacks);
1247 }
1248 
1249 static void match_call_implies(struct symbol *sym)
1250 {
1251         struct implies_info info = {
1252                 .type = CALL_IMPLIES,
1253                 .cb_list = call_implies_cb_list,
1254         };
1255 
1256         if (!sym || !sym->ident)
1257                 return;
1258 
1259         info.sym = sym;
1260         sql_select_implies("function, type, parameter, key, value", &info,
1261                            call_implies_callbacks);
1262 }
1263 























1264 static char *get_return_compare_is_param(struct expression *expr)
1265 {
1266         char *var;
1267         char buf[256];
1268         int comparison;
1269         int param;
1270 
1271         param = get_param_num(expr);
1272         if (param < 0)
1273                 return NULL;
1274 
1275         var = expr_to_var(expr);
1276         if (!var)
1277                 return NULL;
1278         snprintf(buf, sizeof(buf), "%s orig", var);
1279         comparison = get_comparison_strings(var, buf);
1280         free_string(var);
1281 
1282         if (!comparison)
1283                 return NULL;


1289 static char *get_return_compare_str(struct expression *expr)
1290 {
1291         char *compare_str;
1292 
1293         compare_str = get_return_compare_is_param(expr);
1294         if (compare_str)
1295                 return compare_str;
1296 
1297         compare_str = expr_lte_to_param(expr, -1);
1298         if (compare_str)
1299                 return compare_str;
1300 
1301         return expr_param_comparison(expr, -1);
1302 }
1303 
1304 static const char *get_return_ranges_str(struct expression *expr, struct range_list **rl_p)
1305 {
1306         struct range_list *rl;
1307         char *return_ranges;
1308         sval_t sval;

1309         char *compare_str;
1310         char *math_str;
1311         char buf[128];
1312 
1313         *rl_p = NULL;
1314 
1315         if (!expr)
1316                 return alloc_sname("");
1317 
1318         if (get_implied_value(expr, &sval)) {
1319                 sval = sval_cast(cur_func_return_type(), sval);
1320                 *rl_p = alloc_rl(sval, sval);
1321                 return sval_to_str_or_err_ptr(sval);
1322         }
1323 

1324         compare_str = expr_equal_to_param(expr, -1);
1325         math_str = get_value_in_terms_of_parameter_math(expr);
1326 
1327         if (get_implied_rl(expr, &rl) && !is_whole_rl(rl)) {
1328                 rl = cast_rl(cur_func_return_type(), rl);
1329                 return_ranges = show_rl(rl);
1330         } else if (get_imaginary_absolute(expr, &rl)){
1331                 rl = cast_rl(cur_func_return_type(), rl);
1332                 return alloc_sname(show_rl(rl));
1333         } else {
1334                 get_absolute_rl(expr, &rl);
1335                 rl = cast_rl(cur_func_return_type(), rl);
1336                 return_ranges = show_rl(rl);
1337         }
1338         *rl_p = rl;
1339 




1340         if (compare_str) {
1341                 snprintf(buf, sizeof(buf), "%s%s", return_ranges, compare_str);
1342                 return alloc_sname(buf);
1343         }
1344         if (math_str) {
1345                 snprintf(buf, sizeof(buf), "%s[%s]", return_ranges, math_str);
1346                 return alloc_sname(buf);
1347         }
1348         compare_str = get_return_compare_str(expr);
1349         if (compare_str) {
1350                 snprintf(buf, sizeof(buf), "%s%s", return_ranges, compare_str);
1351                 return alloc_sname(buf);
1352         }
1353 
1354         return return_ranges;
1355 }
1356 
1357 static void match_return_info(int return_id, char *return_ranges, struct expression *expr)
1358 {
1359         sql_insert_return_states(return_id, return_ranges, INTERNAL, -1, "", function_signature());


1834          * useful for the callers.
1835          */
1836         FOR_EACH_PTR(sm->possible, tmp) {
1837                 if (is_merged(tmp))
1838                         continue;
1839                 if (!estate_get_single_value(tmp->state, &sval))
1840                         return NULL;
1841         } END_FOR_EACH_PTR(tmp);
1842 
1843         return sm;
1844 }
1845 
1846 static int split_on_bool_sm(struct sm_state *sm, struct expression *expr)
1847 {
1848         struct returned_state_callback *cb;
1849         struct range_list *ret_rl;
1850         const char *return_ranges;
1851         struct sm_state *tmp;
1852         int ret = 0;
1853         int nr_possible, nr_states;
1854         char *compare_str = NULL;
1855         char buf[128];
1856         struct state_list *already_handled = NULL;
1857 
1858         if (!sm || !sm->merged)
1859                 return 0;
1860 
1861         if (too_many_possible(sm))
1862                 return 0;
1863 
1864         /* bail if it gets too complicated */
1865         nr_possible = ptr_list_size((struct ptr_list *)sm->possible);
1866         nr_states = get_db_state_count();
1867         if (nr_states * nr_possible >= 2000)
1868                 return 0;
1869 
1870         FOR_EACH_PTR(sm->possible, tmp) {
1871                 if (tmp->merged)
1872                         continue;
1873                 if (ptr_in_list(tmp, already_handled))
1874                         continue;
1875                 add_ptr_list(&already_handled, tmp);
1876 
1877                 ret = 1;
1878                 __push_fake_cur_stree();
1879 
1880                 overwrite_states_using_pool(sm, tmp);
1881 
1882                 return_ranges = get_return_ranges_str(expr, &ret_rl);
1883                 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                 return_id++;
1891                 FOR_EACH_PTR(returned_state_callbacks, cb) {
1892                         cb->callback(return_id, (char *)return_ranges, expr);
1893                 } END_FOR_EACH_PTR(cb);
1894 
1895                 __free_fake_cur_stree();
1896         } END_FOR_EACH_PTR(tmp);
1897 
1898         free_slist(&already_handled);
1899 
1900         return ret;
1901 }
1902 
1903 static int split_by_bool_param(struct expression *expr)
1904 {
1905         struct sm_state *start_sm, *sm;
1906         sval_t sval;
1907 
1908         start_sm = find_bool_param();
1909         if (!start_sm)


1997                 return;
1998         } else if (call_return_state_hooks_split_null_non_null_zero(expr)) {
1999                 return;
2000         } else if (call_return_state_hooks_split_success_fail(expr)) {
2001                 return;
2002         } else if (splitable_function_call(expr)) {
2003                 return;
2004         } else if (split_by_bool_param(expr)) {
2005         } else if (split_by_null_nonnull_param(expr)) {
2006                 return;
2007         }
2008 
2009 vanilla:
2010         return_ranges = get_return_ranges_str(expr, &ret_rl);
2011         set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));
2012 
2013         return_id++;
2014         nr_states = get_db_state_count();
2015         if (nr_states >= 10000) {
2016                 match_return_info(return_id, (char *)return_ranges, expr);

2017                 mark_all_params_untracked(return_id, (char *)return_ranges, expr);
2018                 return;
2019         }
2020         FOR_EACH_PTR(returned_state_callbacks, cb) {
2021                 cb->callback(return_id, (char *)return_ranges, expr);
2022         } END_FOR_EACH_PTR(cb);
2023 }
2024 
2025 static void print_returned_struct_members(int return_id, char *return_ranges, struct expression *expr)
2026 {
2027         struct returned_member_callback *cb;
2028         struct stree *stree;
2029         struct sm_state *sm;
2030         struct symbol *type;
2031         char *name;
2032         char member_name[256];
2033         int len;
2034 
2035         type = get_type(expr);
2036         if (!type || type->type != SYM_PTR)


2270         if (!token)
2271                 return;
2272         if (token_type(token) != TOKEN_STREAMBEGIN)
2273                 return;
2274         token = token->next;
2275         while (token_type(token) != TOKEN_STREAMEND) {
2276                 if (token_type(token) != TOKEN_IDENT)
2277                         return;
2278                 func = alloc_string(show_ident(token->ident));
2279                 add_ptr_list(&common_funcs, func);
2280                 token = token->next;
2281         }
2282         clear_token_alloc();
2283 }
2284 
2285 static char *get_next_string(char **str)
2286 {
2287         static char string[256];
2288         char *start;
2289         char *p = *str;
2290         int len;
2291 
2292         if (*p == '\0')
2293                 return NULL;
2294         start = p;
2295 
2296         while (*p != '\0' && *p != ' ' && *p != '\n')






2297                 p++;

2298 
2299         len = p - start;
2300         if (len > 256) {
2301                 memcpy(string, start, 255);
2302                 string[255] = '\0';
2303                 sm_ierror("return_fix: '%s' too long", string);
2304                 **str = '\0';
2305                 return NULL;
2306         }
2307         memcpy(string, start, len);
2308         string[len] = '\0';






2309         if (*p != '\0')
2310                 p++;
2311         *str = p;
2312         return string;
2313 }
2314 
2315 static void register_return_replacements(void)
2316 {
2317         char *func, *orig, *new;
2318         char filename[256];
2319         char buf[4096];
2320         int fd, ret, i;
2321         char *p;
2322 
2323         snprintf(filename, 256, "db/%s.return_fixes", option_project_str);
2324         fd = open_schema_file(filename);
2325         if (fd < 0)
2326                 return;
2327         ret = read(fd, buf, sizeof(buf));
2328         close(fd);


2482         if (strcmp("$", key) == 0)
2483                 return expr_to_chunk_sym_vsl(arg, sym, vsl);
2484         return get_variable_from_key(arg, key, sym);
2485 }
2486 
2487 const char *state_name_to_param_name(const char *state_name, const char *param_name)
2488 {
2489         int name_len;
2490         static char buf[256];
2491         bool add_star = false;
2492 
2493         name_len = strlen(param_name);
2494 
2495         if (state_name[0] == '*') {
2496                 add_star = true;
2497                 state_name++;
2498         }
2499 
2500         if (strcmp(state_name, param_name) == 0) {
2501                 snprintf(buf, sizeof(buf), "%s$", add_star ? "*" : "");
2502                 return buf;
2503         }
2504 
2505         if (state_name[name_len] == '-' && /* check for '-' from "->" */
2506             strncmp(state_name, param_name, name_len) == 0) {
2507                 snprintf(buf, sizeof(buf), "%s$%s",
2508                          add_star ? "*" : "", state_name + name_len);
2509                 return buf;
2510         }
2511         return NULL;
2512 }
2513 
2514 const char *get_param_name_var_sym(const char *name, struct symbol *sym)
2515 {
2516         if (!sym || !sym->ident)
2517                 return NULL;
2518 
2519         return state_name_to_param_name(name, sym->ident->name);
2520 }
2521 
2522 const char *get_mtag_name_var_sym(const char *state_name, struct symbol *sym)
2523 {
2524         struct symbol *type;
2525         const char *sym_name;
2526         int name_len;
2527         static char buf[256];
2528 
2529         /*




 491         run_sql(callback, info,
 492                 "select %s from return_states join function_ptr where "
 493                 "return_states.function == function_ptr.function and ptr = '%s' "
 494                 "and searchable = 1 "
 495                 "order by function_ptr.file, return_states.file, return_id, type;",
 496                 cols, ptr);
 497 }
 498 
 499 static int is_local_symbol(struct expression *expr)
 500 {
 501         if (expr->type != EXPR_SYMBOL)
 502                 return 0;
 503         if (expr->symbol->ctype.modifiers & (MOD_NONLOCAL | MOD_STATIC | MOD_ADDRESSABLE))
 504                 return 0;
 505         return 1;
 506 }
 507 
 508 void sql_select_return_states(const char *cols, struct expression *call,
 509         int (*callback)(void*, int, char**, char**), void *info)
 510 {
 511         struct expression *fn;
 512         int row_count = 0;
 513 
 514         if (is_fake_call(call))
 515                 return;
 516 
 517         fn = strip_expr(call->fn);
 518         if (fn->type != EXPR_SYMBOL || !fn->symbol || is_local_symbol(fn)) {
 519                 sql_select_return_states_pointer(cols, call, callback, info);
 520                 return;
 521         }
 522 
 523         if (inlinable(fn)) {
 524                 mem_sql(callback, info,
 525                         "select %s from return_states where call_id = '%lu' order by return_id, type;",
 526                         cols, (unsigned long)call);
 527                 return;
 528         }
 529 
 530         run_sql(get_row_count, &row_count, "select count(*) from return_states where %s;",
 531                 get_static_filter(fn->symbol));
 532         if (row_count > 3000)
 533                 return;
 534 
 535         run_sql(callback, info, "select %s from return_states where %s order by file, return_id, type;",
 536                 cols, get_static_filter(fn->symbol));
 537 }
 538 
 539 #define CALL_IMPLIES 0
 540 #define RETURN_IMPLIES 1
 541 
 542 struct implies_info {
 543         int type;
 544         struct db_implies_cb_list *cb_list;
 545         struct expression *expr;
 546         struct symbol *sym;
 547 };
 548 
 549 void sql_select_implies(const char *cols, struct implies_info *info,
 550         int (*callback)(void*, int, char**, char**))
 551 {
 552         if (info->type == RETURN_IMPLIES && inlinable(info->expr->fn)) {
 553                 mem_sql(callback, info,
 554                         "select %s from return_implies where call_id = '%lu';",
 555                         cols, (unsigned long)info->expr);
 556                 return;


 703                         "select distinct return from return_states where %s;",
 704                         get_static_filter(expr->fn->symbol));
 705         }
 706         return ret_info.return_range_list;
 707 }
 708 
 709 struct range_list *db_return_vals_from_str(const char *fn_name)
 710 {
 711         struct return_info ret_info;
 712 
 713         ret_info.static_returns_call = NULL;
 714         ret_info.return_type = &llong_ctype;
 715         ret_info.return_range_list = NULL;
 716 
 717         run_sql(db_return_callback, &ret_info,
 718                 "select distinct return from return_states where function = '%s';",
 719                 fn_name);
 720         return ret_info.return_range_list;
 721 }
 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 
 750 static void match_call_marker(struct expression *expr)
 751 {
 752         struct symbol *type;
 753 
 754         type = get_type(expr->fn);
 755         if (type && type->type == SYM_PTR)
 756                 type = get_real_base_type(type);
 757 
 758         /*
 759          * we just want to record something in the database so that if we have
 760          * two calls like:  frob(4); frob(some_unkown); then on the receiving
 761          * side we know that sometimes frob is called with unknown parameters.
 762          */
 763 
 764         sql_insert_caller_info(expr, INTERNAL, -1, "%call_marker%", type_to_str(type));
 765 }
 766 
 767 static char *show_offset(int offset)
 768 {
 769         static char buf[64];


1118 
1119         if (!sym || !sym->ident)
1120                 return;
1121 
1122         gettimeofday(&data.start_time, NULL);
1123 
1124         __push_fake_cur_stree();
1125         __unnullify_path();
1126 
1127         if (!__inline_fn) {
1128                 char *ptr;
1129 
1130                 if (sym->ctype.modifiers & MOD_STATIC)
1131                         get_ptr_names(get_base_file(), sym->ident->name);
1132                 else
1133                         get_ptr_names(NULL, sym->ident->name);
1134 
1135                 if (ptr_list_size((struct ptr_list *)ptr_names) > 20) {
1136                         __free_ptr_list((struct ptr_list **)&ptr_names);
1137                         __free_ptr_list((struct ptr_list **)&ptr_names_done);
1138                         __free_fake_cur_stree();

1139                         return;
1140                 }
1141 
1142                 sql_select_caller_info(&data,
1143                                        "call_id, type, parameter, key, value",
1144                                        sym);
1145 
1146 
1147                 stree = __pop_fake_cur_stree();
1148                 if (!data.ignore)
1149                         merge_stree(&data.final_states, stree);
1150                 free_stree(&stree);
1151                 __push_fake_cur_stree();
1152                 __unnullify_path();
1153                 data.prev_func_id = -1;
1154                 data.ignore = 0;
1155                 data.results = 0;
1156 
1157                 FOR_EACH_PTR(ptr_names, ptr) {
1158                         run_sql(caller_info_callback, &data,
1159                                 "select call_id, type, parameter, key, value"
1160                                 " from common_caller_info where function = '%s' order by call_id",
1161                                 ptr);
1162                 } END_FOR_EACH_PTR(ptr);
1163 
1164                 if (data.results) {
1165                         FOR_EACH_PTR(ptr_names, ptr) {
1166                                 free_string(ptr);
1167                         } END_FOR_EACH_PTR(ptr);
1168                         goto free_ptr_names;
1169                 }
1170 
1171                 FOR_EACH_PTR(ptr_names, ptr) {
1172                         run_sql(caller_info_callback, &data,
1173                                 "select call_id, type, parameter, key, value"
1174                                 " from caller_info where function = '%s' order by call_id",
1175                                 ptr);


1273         info.sym = expr->fn->symbol;
1274         sql_select_implies("function, type, parameter, key, value", &info,
1275                            return_implies_callbacks);
1276 }
1277 
1278 static void match_call_implies(struct symbol *sym)
1279 {
1280         struct implies_info info = {
1281                 .type = CALL_IMPLIES,
1282                 .cb_list = call_implies_cb_list,
1283         };
1284 
1285         if (!sym || !sym->ident)
1286                 return;
1287 
1288         info.sym = sym;
1289         sql_select_implies("function, type, parameter, key, value", &info,
1290                            call_implies_callbacks);
1291 }
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 
1316 static char *get_return_compare_is_param(struct expression *expr)
1317 {
1318         char *var;
1319         char buf[256];
1320         int comparison;
1321         int param;
1322 
1323         param = get_param_num(expr);
1324         if (param < 0)
1325                 return NULL;
1326 
1327         var = expr_to_var(expr);
1328         if (!var)
1329                 return NULL;
1330         snprintf(buf, sizeof(buf), "%s orig", var);
1331         comparison = get_comparison_strings(var, buf);
1332         free_string(var);
1333 
1334         if (!comparison)
1335                 return NULL;


1341 static char *get_return_compare_str(struct expression *expr)
1342 {
1343         char *compare_str;
1344 
1345         compare_str = get_return_compare_is_param(expr);
1346         if (compare_str)
1347                 return compare_str;
1348 
1349         compare_str = expr_lte_to_param(expr, -1);
1350         if (compare_str)
1351                 return compare_str;
1352 
1353         return expr_param_comparison(expr, -1);
1354 }
1355 
1356 static const char *get_return_ranges_str(struct expression *expr, struct range_list **rl_p)
1357 {
1358         struct range_list *rl;
1359         char *return_ranges;
1360         sval_t sval;
1361         char *fn_param_str;
1362         char *compare_str;
1363         char *math_str;
1364         char buf[128];
1365 
1366         *rl_p = NULL;
1367 
1368         if (!expr)
1369                 return alloc_sname("");
1370 
1371         if (get_implied_value(expr, &sval)) {
1372                 sval = sval_cast(cur_func_return_type(), sval);
1373                 *rl_p = alloc_rl(sval, sval);
1374                 return sval_to_str_or_err_ptr(sval);
1375         }
1376 
1377         fn_param_str = get_fn_param_str(expr);
1378         compare_str = expr_equal_to_param(expr, -1);
1379         math_str = get_value_in_terms_of_parameter_math(expr);
1380 
1381         if (get_implied_rl(expr, &rl) && !is_whole_rl(rl)) {
1382                 rl = cast_rl(cur_func_return_type(), rl);
1383                 return_ranges = show_rl(rl);
1384         } else if (get_imaginary_absolute(expr, &rl)){
1385                 rl = cast_rl(cur_func_return_type(), rl);
1386                 return alloc_sname(show_rl(rl));
1387         } else {
1388                 get_absolute_rl(expr, &rl);
1389                 rl = cast_rl(cur_func_return_type(), rl);
1390                 return_ranges = show_rl(rl);
1391         }
1392         *rl_p = rl;
1393 
1394         if (fn_param_str) {
1395                 snprintf(buf, sizeof(buf), "%s%s", return_ranges, fn_param_str);
1396                 return alloc_sname(buf);
1397         }
1398         if (compare_str) {
1399                 snprintf(buf, sizeof(buf), "%s%s", return_ranges, compare_str);
1400                 return alloc_sname(buf);
1401         }
1402         if (math_str) {
1403                 snprintf(buf, sizeof(buf), "%s[%s]", return_ranges, math_str);
1404                 return alloc_sname(buf);
1405         }
1406         compare_str = get_return_compare_str(expr);
1407         if (compare_str) {
1408                 snprintf(buf, sizeof(buf), "%s%s", return_ranges, compare_str);
1409                 return alloc_sname(buf);
1410         }
1411 
1412         return return_ranges;
1413 }
1414 
1415 static void match_return_info(int return_id, char *return_ranges, struct expression *expr)
1416 {
1417         sql_insert_return_states(return_id, return_ranges, INTERNAL, -1, "", function_signature());


1892          * useful for the callers.
1893          */
1894         FOR_EACH_PTR(sm->possible, tmp) {
1895                 if (is_merged(tmp))
1896                         continue;
1897                 if (!estate_get_single_value(tmp->state, &sval))
1898                         return NULL;
1899         } END_FOR_EACH_PTR(tmp);
1900 
1901         return sm;
1902 }
1903 
1904 static int split_on_bool_sm(struct sm_state *sm, struct expression *expr)
1905 {
1906         struct returned_state_callback *cb;
1907         struct range_list *ret_rl;
1908         const char *return_ranges;
1909         struct sm_state *tmp;
1910         int ret = 0;
1911         int nr_possible, nr_states;


1912         struct state_list *already_handled = NULL;
1913 
1914         if (!sm || !sm->merged)
1915                 return 0;
1916 
1917         if (too_many_possible(sm))
1918                 return 0;
1919 
1920         /* bail if it gets too complicated */
1921         nr_possible = ptr_list_size((struct ptr_list *)sm->possible);
1922         nr_states = get_db_state_count();
1923         if (nr_states * nr_possible >= 2000)
1924                 return 0;
1925 
1926         FOR_EACH_PTR(sm->possible, tmp) {
1927                 if (tmp->merged)
1928                         continue;
1929                 if (ptr_in_list(tmp, already_handled))
1930                         continue;
1931                 add_ptr_list(&already_handled, tmp);
1932 
1933                 ret = 1;
1934                 __push_fake_cur_stree();
1935 
1936                 overwrite_states_using_pool(sm, tmp);
1937 
1938                 return_ranges = get_return_ranges_str(expr, &ret_rl);
1939                 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));






1940                 return_id++;
1941                 FOR_EACH_PTR(returned_state_callbacks, cb) {
1942                         cb->callback(return_id, (char *)return_ranges, expr);
1943                 } END_FOR_EACH_PTR(cb);
1944 
1945                 __free_fake_cur_stree();
1946         } END_FOR_EACH_PTR(tmp);
1947 
1948         free_slist(&already_handled);
1949 
1950         return ret;
1951 }
1952 
1953 static int split_by_bool_param(struct expression *expr)
1954 {
1955         struct sm_state *start_sm, *sm;
1956         sval_t sval;
1957 
1958         start_sm = find_bool_param();
1959         if (!start_sm)


2047                 return;
2048         } else if (call_return_state_hooks_split_null_non_null_zero(expr)) {
2049                 return;
2050         } else if (call_return_state_hooks_split_success_fail(expr)) {
2051                 return;
2052         } else if (splitable_function_call(expr)) {
2053                 return;
2054         } else if (split_by_bool_param(expr)) {
2055         } else if (split_by_null_nonnull_param(expr)) {
2056                 return;
2057         }
2058 
2059 vanilla:
2060         return_ranges = get_return_ranges_str(expr, &ret_rl);
2061         set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));
2062 
2063         return_id++;
2064         nr_states = get_db_state_count();
2065         if (nr_states >= 10000) {
2066                 match_return_info(return_id, (char *)return_ranges, expr);
2067                 print_limited_param_set(return_id, (char *)return_ranges, expr);
2068                 mark_all_params_untracked(return_id, (char *)return_ranges, expr);
2069                 return;
2070         }
2071         FOR_EACH_PTR(returned_state_callbacks, cb) {
2072                 cb->callback(return_id, (char *)return_ranges, expr);
2073         } END_FOR_EACH_PTR(cb);
2074 }
2075 
2076 static void print_returned_struct_members(int return_id, char *return_ranges, struct expression *expr)
2077 {
2078         struct returned_member_callback *cb;
2079         struct stree *stree;
2080         struct sm_state *sm;
2081         struct symbol *type;
2082         char *name;
2083         char member_name[256];
2084         int len;
2085 
2086         type = get_type(expr);
2087         if (!type || type->type != SYM_PTR)


2321         if (!token)
2322                 return;
2323         if (token_type(token) != TOKEN_STREAMBEGIN)
2324                 return;
2325         token = token->next;
2326         while (token_type(token) != TOKEN_STREAMEND) {
2327                 if (token_type(token) != TOKEN_IDENT)
2328                         return;
2329                 func = alloc_string(show_ident(token->ident));
2330                 add_ptr_list(&common_funcs, func);
2331                 token = token->next;
2332         }
2333         clear_token_alloc();
2334 }
2335 
2336 static char *get_next_string(char **str)
2337 {
2338         static char string[256];
2339         char *start;
2340         char *p = *str;
2341         int len, i, j;
2342 
2343         if (*p == '\0')
2344                 return NULL;
2345         start = p;
2346 
2347         while (*p != '\0' && *p != '\n') {
2348                 if (*p == '\\' && *(p + 1) == ' ') {
2349                         p += 2;
2350                         continue;
2351                 }
2352                 if (*p == ' ')
2353                         break;
2354                 p++;
2355         }
2356 
2357         len = p - start;
2358         if (len >= sizeof(string)) {
2359                 memcpy(string, start, sizeof(string));
2360                 string[sizeof(string) - 1] = '\0';
2361                 sm_ierror("return_fix: '%s' too long", string);
2362                 **str = '\0';
2363                 return NULL;
2364         }
2365         memcpy(string, start, len);
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         }
2373         if (*p != '\0')
2374                 p++;
2375         *str = p;
2376         return string;
2377 }
2378 
2379 static void register_return_replacements(void)
2380 {
2381         char *func, *orig, *new;
2382         char filename[256];
2383         char buf[4096];
2384         int fd, ret, i;
2385         char *p;
2386 
2387         snprintf(filename, 256, "db/%s.return_fixes", option_project_str);
2388         fd = open_schema_file(filename);
2389         if (fd < 0)
2390                 return;
2391         ret = read(fd, buf, sizeof(buf));
2392         close(fd);


2546         if (strcmp("$", key) == 0)
2547                 return expr_to_chunk_sym_vsl(arg, sym, vsl);
2548         return get_variable_from_key(arg, key, sym);
2549 }
2550 
2551 const char *state_name_to_param_name(const char *state_name, const char *param_name)
2552 {
2553         int name_len;
2554         static char buf[256];
2555         bool add_star = false;
2556 
2557         name_len = strlen(param_name);
2558 
2559         if (state_name[0] == '*') {
2560                 add_star = true;
2561                 state_name++;
2562         }
2563 
2564         if (strcmp(state_name, param_name) == 0) {
2565                 snprintf(buf, sizeof(buf), "%s$", add_star ? "*" : "");
2566                 return alloc_sname(buf);
2567         }
2568 
2569         if (state_name[name_len] == '-' && /* check for '-' from "->" */
2570             strncmp(state_name, param_name, name_len) == 0) {
2571                 snprintf(buf, sizeof(buf), "%s$%s",
2572                          add_star ? "*" : "", state_name + name_len);
2573                 return alloc_sname(buf);
2574         }
2575         return NULL;
2576 }
2577 
2578 const char *get_param_name_var_sym(const char *name, struct symbol *sym)
2579 {
2580         if (!sym || !sym->ident)
2581                 return NULL;
2582 
2583         return state_name_to_param_name(name, sym->ident->name);
2584 }
2585 
2586 const char *get_mtag_name_var_sym(const char *state_name, struct symbol *sym)
2587 {
2588         struct symbol *type;
2589         const char *sym_name;
2590         int name_len;
2591         static char buf[256];
2592 
2593         /*