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 /*
|