Print this page
12724 update smatch to 0.6.1-rc1-il-5


 340                         continue;
 341                 if (!false_comparison_range_LR(comparison, tmp->range, value_range, left))
 342                         continue;
 343                 (tmp->u.ranged)(fn, expr, NULL, tmp->info);
 344         } END_FOR_EACH_PTR(tmp);
 345         tmp_stree = __pop_fake_cur_stree();
 346         merge_fake_stree(&false_states, tmp_stree);
 347         free_stree(&tmp_stree);
 348 
 349         *implied_true = true_states;
 350         *implied_false = false_states;
 351 }
 352 
 353 struct db_callback_info {
 354         int true_side;
 355         int comparison;
 356         struct expression *expr;
 357         struct range_list *rl;
 358         int left;
 359         struct stree *stree;

 360         struct db_implies_list *callbacks;
 361         int prev_return_id;
 362         int cull;
 363         int has_states;
 364         char *ret_str;
 365         struct smatch_state *ret_state;
 366         struct expression *var_expr;
 367         int handled;
 368 };
 369 











 370 static void store_return_state(struct db_callback_info *db_info, const char *ret_str, struct smatch_state *state)
 371 {
 372         db_info->ret_str = alloc_sname(ret_str),
 373         db_info->ret_state = state;
 374 }
 375 
 376 static bool fake_a_param_assignment(struct expression *expr, const char *return_str, struct smatch_state *orig)
 377 {
 378         struct expression *arg, *left, *right, *tmp, *fake_assign;
 379         char *p;
 380         int param;
 381         char buf[256];
 382         char *str;
 383 
 384         if (expr->type != EXPR_ASSIGNMENT || expr->op != '=')
 385                 return false;
 386         left = expr->left;
 387         right = expr->right;
 388 
 389         while (right->type == EXPR_ASSIGNMENT)


 443          * is maybe (-4)-65531 but we know it is in the 0-65531 range so both
 444          * parts have to be considered.  We use _nomod() because it's not really
 445          * another modification, it's just a clarification.
 446          *
 447          */
 448         if (estate_rl(orig)) {
 449                 struct smatch_state *faked;
 450                 struct range_list *rl;
 451 
 452                 faked = get_extra_state(left);
 453                 if (estate_rl(faked)) {
 454                         rl = rl_intersection(estate_rl(faked), estate_rl(orig));
 455                         if (rl)
 456                                 set_extra_expr_nomod(expr, alloc_estate_rl(rl));
 457                 }
 458         }
 459 
 460         return true;
 461 }
 462 




















 463 static void set_return_assign_state(struct db_callback_info *db_info)
 464 {
 465         struct expression *expr = db_info->expr->left;
 466         struct smatch_state *state;
 467 
 468         if (!db_info->ret_state)
 469                 return;
 470 
 471         state = alloc_estate_rl(cast_rl(get_type(expr), clone_rl(estate_rl(db_info->ret_state))));
 472         if (!fake_a_param_assignment(db_info->expr, db_info->ret_str, state))
 473                 set_extra_expr_mod(expr, state);
 474 
 475         db_info->ret_state = NULL;
 476         db_info->ret_str = NULL;
 477 }
 478 
 479 static void set_other_side_state(struct db_callback_info *db_info)
 480 {
 481         struct expression *expr = db_info->var_expr;
 482         struct smatch_state *state;


 618         int type, param;
 619         char *ret_str, *key, *value;
 620         struct return_implies_callback *tmp;
 621         struct stree *stree;
 622         int return_id;
 623         int comparison;
 624 
 625         if (argc != 6)
 626                 return 0;
 627 
 628         return_id = atoi(argv[0]);
 629         ret_str = argv[1];
 630         type = atoi(argv[2]);
 631         param = atoi(argv[3]);
 632         key = argv[4];
 633         value = argv[5];
 634 
 635         db_info->has_states = 1;
 636         if (db_info->prev_return_id != -1 && type == INTERNAL) {
 637                 set_other_side_state(db_info);

 638                 stree = __pop_fake_cur_stree();
 639 
 640                 if (!db_info->cull)
 641                         merge_fake_stree(&db_info->stree, stree);
 642                 free_stree(&stree);
 643                 __push_fake_cur_stree();
 644                 db_info->cull = 0;
 645         }
 646         db_info->prev_return_id = return_id;
 647 
 648         if (type == INTERNAL && func_type_mismatch(db_info->expr, value))
 649                 db_info->cull = 1;
 650         if (db_info->cull)
 651                 return 0;
 652         if (type == CULL_PATH) {
 653                 db_info->cull = 1;
 654                 return 0;
 655         }
 656 
 657         if (is_impossible_data(type, db_info->expr, param, key, value)) {
 658                 db_info->cull = 1;
 659                 return 0;
 660         }
 661 
 662         call_results_to_rl(db_info->expr, get_type(strip_expr(db_info->expr)), ret_str, &ret_range);
 663         ret_range = cast_rl(get_type(db_info->expr), ret_range);
 664         if (!ret_range)
 665                 ret_range = alloc_whole_rl(get_type(db_info->expr));
 666 
 667         comparison = db_info->comparison;
 668         if (db_info->left)
 669                 comparison = flip_comparison(comparison);
 670 
 671         if (db_info->true_side) {
 672                 if (!possibly_true_rl(var_rl, comparison, ret_range))
 673                         return 0;
 674                 if (type == PARAM_LIMIT)
 675                         param_limit_implications(db_info->expr, param, key, value);
 676                 filter_by_comparison(&var_rl, comparison, ret_range);
 677                 filter_by_comparison(&ret_range, flip_comparison(comparison), var_rl);
 678         } else {
 679                 if (!possibly_false_rl(var_rl, comparison, ret_range))
 680                         return 0;
 681                 if (type == PARAM_LIMIT)
 682                         param_limit_implications(db_info->expr, param, key, value);
 683                 filter_by_comparison(&var_rl, negate_comparison(comparison), ret_range);
 684                 filter_by_comparison(&ret_range, flip_comparison(negate_comparison(comparison)), var_rl);
 685         }
 686 
 687         handle_ret_equals_param(ret_str, ret_range, db_info->expr);
 688 
 689         if (type == INTERNAL) {
 690                 set_state(-1, "unnull_path", NULL, &true_state);
 691                 __add_return_comparison(strip_expr(db_info->expr), ret_str);
 692                 __add_return_to_param_mapping(db_info->expr, ret_str);
 693                 store_return_state(db_info, ret_str, alloc_estate_rl(clone_rl(var_rl)));
 694         }
 695 
 696         FOR_EACH_PTR(db_info->callbacks, tmp) {
 697                 if (tmp->type == type)
 698                         tmp->callback(db_info->expr, param, key, value);
 699         } END_FOR_EACH_PTR(tmp);
 700 
 701         return 0;
 702 }


 727         }
 728 
 729         get_absolute_rl(var_expr, &rl);
 730 
 731         db_info.comparison = comparison;
 732         db_info.expr = call_expr;
 733         db_info.rl = rl;
 734         db_info.left = call_on_left;
 735         db_info.callbacks = db_return_states_list;
 736         db_info.var_expr = var_expr;
 737 
 738         call_return_states_before_hooks();
 739 
 740         db_info.true_side = 1;
 741         db_info.stree = NULL;
 742         db_info.prev_return_id = -1;
 743         __push_fake_cur_stree();
 744         sql_select_return_states("return_id, return, type, parameter, key, value",
 745                                  call_expr, db_compare_callback, &db_info);
 746         set_other_side_state(&db_info);

 747         stree = __pop_fake_cur_stree();
 748         if (!db_info.cull)
 749                 merge_fake_stree(&db_info.stree, stree);
 750         free_stree(&stree);
 751         true_states = db_info.stree;
 752         if (!true_states && db_info.has_states) {
 753                 __push_fake_cur_stree();
 754                 set_path_impossible();
 755                 true_states = __pop_fake_cur_stree();
 756         }
 757 
 758         nullify_path();
 759         __unnullify_path();
 760         FOR_EACH_SM(orig_states, sm) {
 761                 __set_sm_cur_stree(sm);
 762         } END_FOR_EACH_SM(sm);
 763 
 764         db_info.true_side = 0;
 765         db_info.stree = NULL;
 766         db_info.prev_return_id = -1;
 767         db_info.cull = 0;
 768         __push_fake_cur_stree();
 769         sql_select_return_states("return_id, return, type, parameter, key, value", call_expr,
 770                         db_compare_callback, &db_info);
 771         set_other_side_state(&db_info);

 772         stree = __pop_fake_cur_stree();
 773         if (!db_info.cull)
 774                 merge_fake_stree(&db_info.stree, stree);
 775         free_stree(&stree);
 776         false_states = db_info.stree;
 777         if (!false_states && db_info.has_states) {
 778                 __push_fake_cur_stree();
 779                 set_path_impossible();
 780                 false_states = __pop_fake_cur_stree();
 781         }
 782 
 783         nullify_path();
 784         __unnullify_path();
 785         FOR_EACH_SM(orig_states, sm) {
 786                 __set_sm_cur_stree(sm);
 787         } END_FOR_EACH_SM(sm);
 788 
 789         free_stree(&orig_states);
 790 
 791         FOR_EACH_SM(true_states, sm) {


 876         struct range_list *ret_range;
 877         int type, param;
 878         char *ret_str, *key, *value;
 879         struct return_implies_callback *tmp;
 880         struct stree *stree;
 881         int return_id;
 882 
 883         if (argc != 6)
 884                 return 0;
 885 
 886         return_id = atoi(argv[0]);
 887         ret_str = argv[1];
 888         type = atoi(argv[2]);
 889         param = atoi(argv[3]);
 890         key = argv[4];
 891         value = argv[5];
 892 
 893         if (db_info->prev_return_id != -1 && type == INTERNAL) {
 894                 call_ranged_return_hooks(db_info);
 895                 set_return_assign_state(db_info);

 896                 stree = __pop_fake_cur_stree();
 897                 if (!db_info->cull)
 898                         merge_fake_stree(&db_info->stree, stree);
 899                 free_stree(&stree);
 900                 __push_fake_cur_stree();
 901                 db_info->cull = 0;
 902         }
 903         db_info->prev_return_id = return_id;
 904 
 905         if (type == INTERNAL && func_type_mismatch(db_info->expr, value))
 906                 db_info->cull = 1;
 907         if (db_info->cull)
 908                 return 0;
 909         if (type == CULL_PATH) {
 910                 db_info->cull = 1;
 911                 return 0;
 912         }
 913         if (is_impossible_data(type, db_info->expr, param, key, value)) {
 914                 db_info->cull = 1;
 915                 return 0;
 916         }
 917 
 918         if (type == PARAM_LIMIT)
 919                 param_limit_implications(db_info->expr, param, key, value);
 920 
 921         db_info->handled = 1;
 922         call_results_to_rl(db_info->expr->right, get_type(strip_expr(db_info->expr->right)), ret_str, &ret_range);
 923         if (!ret_range)
 924                 ret_range = alloc_whole_rl(get_type(strip_expr(db_info->expr->right)));
 925         ret_range = cast_rl(get_type(db_info->expr->right), ret_range);
 926 
 927         if (type == INTERNAL) {
 928                 set_state(-1, "unnull_path", NULL, &true_state);
 929                 __add_return_comparison(strip_expr(db_info->expr->right), ret_str);
 930                 __add_comparison_info(db_info->expr->left, strip_expr(db_info->expr->right), ret_str);
 931                 __add_return_to_param_mapping(db_info->expr, ret_str);
 932                 store_return_state(db_info, ret_str, alloc_estate_rl(ret_range));

 933         }
 934 
 935         FOR_EACH_PTR(db_return_states_list, tmp) {
 936                 if (tmp->type == type)
 937                         tmp->callback(db_info->expr, param, key, value);
 938         } END_FOR_EACH_PTR(tmp);
 939 
 940         return 0;
 941 }
 942 
 943 static int db_return_states_assign(struct expression *expr)
 944 {
 945         struct expression *right;
 946         struct sm_state *sm;
 947         struct stree *stree;
 948         struct db_callback_info db_info = {};
 949 
 950         right = strip_expr(expr->right);
 951 
 952         db_info.prev_return_id = -1;
 953         db_info.expr = expr;
 954         db_info.stree = NULL;
 955         db_info.handled = 0;
 956 
 957         call_return_states_before_hooks();
 958 
 959         __push_fake_cur_stree();
 960         sql_select_return_states("return_id, return, type, parameter, key, value",
 961                         right, db_assign_return_states_callback, &db_info);
 962         if (option_debug) {
 963                 sm_msg("%s return_id %d return_ranges %s",
 964                         db_info.cull ? "culled" : "merging",
 965                         db_info.prev_return_id,
 966                         db_info.ret_state ? db_info.ret_state->name : "'<empty>'");
 967         }
 968         if (db_info.handled)
 969                 call_ranged_return_hooks(&db_info);
 970         set_return_assign_state(&db_info);

 971         stree = __pop_fake_cur_stree();
 972         if (!db_info.cull)
 973                 merge_fake_stree(&db_info.stree, stree);
 974         free_stree(&stree);
 975 
 976         if (!db_info.stree && db_info.cull) { /* this means we culled everything */
 977                 set_extra_expr_mod(expr->left, alloc_estate_whole(get_type(expr->left)));
 978                 set_path_impossible();
 979         }
 980         FOR_EACH_SM(db_info.stree, sm) {
 981                 __set_sm(sm);
 982         } END_FOR_EACH_SM(sm);
 983 
 984         free_stree(&db_info.stree);
 985         call_return_states_after_hooks(right);
 986 
 987         return db_info.handled;
 988 }
 989 
 990 static int handle_implied_return(struct expression *expr)


1062         struct range_list *ret_range;
1063         int type, param;
1064         char *ret_str, *key, *value;
1065         struct return_implies_callback *tmp;
1066         struct stree *stree;
1067         int return_id;
1068         char buf[64];
1069 
1070         if (argc != 6)
1071                 return 0;
1072 
1073         return_id = atoi(argv[0]);
1074         ret_str = argv[1];
1075         type = atoi(argv[2]);
1076         param = atoi(argv[3]);
1077         key = argv[4];
1078         value = argv[5];
1079 
1080         if (db_info->prev_return_id != -1 && type == INTERNAL) {
1081                 call_ranged_return_hooks(db_info);

1082                 stree = __pop_fake_cur_stree();
1083                 if (!db_info->cull)
1084                         merge_fake_stree(&db_info->stree, stree);
1085                 free_stree(&stree);
1086                 __push_fake_cur_stree();
1087                 __unnullify_path();
1088                 db_info->cull = 0;
1089         }
1090         db_info->prev_return_id = return_id;
1091 
1092         if (type == INTERNAL && func_type_mismatch(db_info->expr, value))
1093                 db_info->cull = 1;
1094         if (db_info->cull)
1095                 return 0;
1096         if (type == CULL_PATH) {
1097                 db_info->cull = 1;
1098                 return 0;
1099         }
1100         if (is_impossible_data(type, db_info->expr, param, key, value)) {
1101                 db_info->cull = 1;
1102                 return 0;
1103         }
1104 
1105         if (type == PARAM_LIMIT)
1106                 param_limit_implications(db_info->expr, param, key, value);
1107 
1108         call_results_to_rl(db_info->expr, get_type(strip_expr(db_info->expr)), ret_str, &ret_range);
1109         ret_range = cast_rl(get_type(db_info->expr), ret_range);
1110 
1111         if (type == INTERNAL) {
1112                 struct smatch_state *state;
1113 
1114                 set_state(-1, "unnull_path", NULL, &true_state);
1115                 __add_return_comparison(strip_expr(db_info->expr), ret_str);
1116                 __add_return_to_param_mapping(db_info->expr, ret_str);
1117                 /*
1118                  * We want to store the return values so that we can split the strees
1119                  * in smatch_db.c.  This uses set_state() directly because it's not a
1120                  * real smatch_extra state.
1121                  */
1122                 snprintf(buf, sizeof(buf), "return %p", db_info->expr);
1123                 state = alloc_estate_rl(ret_range);
1124                 set_state(SMATCH_EXTRA, buf, NULL, state);
1125                 store_return_state(db_info, ret_str, state);
1126         }


1137 static void db_return_states(struct expression *expr)
1138 {
1139         struct sm_state *sm;
1140         struct stree *stree;
1141         struct db_callback_info db_info = {};
1142 
1143         if (!__get_cur_stree())  /* no return functions */
1144                 return;
1145 
1146         db_info.prev_return_id = -1;
1147         db_info.expr = expr;
1148         db_info.stree = NULL;
1149 
1150         call_return_states_before_hooks();
1151 
1152         __push_fake_cur_stree();
1153         __unnullify_path();
1154         sql_select_return_states("return_id, return, type, parameter, key, value",
1155                         expr, db_return_states_callback, &db_info);
1156         call_ranged_return_hooks(&db_info);

1157         stree = __pop_fake_cur_stree();
1158         if (!db_info.cull)
1159                 merge_fake_stree(&db_info.stree, stree);
1160         free_stree(&stree);
1161 
1162         FOR_EACH_SM(db_info.stree, sm) {
1163                 __set_sm(sm);
1164         } END_FOR_EACH_SM(sm);
1165 
1166         free_stree(&db_info.stree);
1167         call_return_states_after_hooks(expr);
1168 }
1169 
1170 static int is_condition_call(struct expression *expr)
1171 {
1172         struct expression *tmp;
1173 
1174         FOR_EACH_PTR_REVERSE(big_condition_stack, tmp) {
1175                 if (expr == tmp || expr_get_parent_expr(expr) == tmp)
1176                         return 1;




 340                         continue;
 341                 if (!false_comparison_range_LR(comparison, tmp->range, value_range, left))
 342                         continue;
 343                 (tmp->u.ranged)(fn, expr, NULL, tmp->info);
 344         } END_FOR_EACH_PTR(tmp);
 345         tmp_stree = __pop_fake_cur_stree();
 346         merge_fake_stree(&false_states, tmp_stree);
 347         free_stree(&tmp_stree);
 348 
 349         *implied_true = true_states;
 350         *implied_false = false_states;
 351 }
 352 
 353 struct db_callback_info {
 354         int true_side;
 355         int comparison;
 356         struct expression *expr;
 357         struct range_list *rl;
 358         int left;
 359         struct stree *stree;
 360         struct stree *implied;
 361         struct db_implies_list *callbacks;
 362         int prev_return_id;
 363         int cull;
 364         int has_states;
 365         char *ret_str;
 366         struct smatch_state *ret_state;
 367         struct expression *var_expr;
 368         int handled;
 369 };
 370 
 371 static void set_implied_states(struct db_callback_info *db_info)
 372 {
 373         struct sm_state *sm;
 374 
 375         FOR_EACH_SM(db_info->implied, sm) {
 376                 __set_sm(sm);
 377         } END_FOR_EACH_SM(sm);
 378 
 379         free_stree(&db_info->implied);
 380 }
 381 
 382 static void store_return_state(struct db_callback_info *db_info, const char *ret_str, struct smatch_state *state)
 383 {
 384         db_info->ret_str = alloc_sname(ret_str),
 385         db_info->ret_state = state;
 386 }
 387 
 388 static bool fake_a_param_assignment(struct expression *expr, const char *return_str, struct smatch_state *orig)
 389 {
 390         struct expression *arg, *left, *right, *tmp, *fake_assign;
 391         char *p;
 392         int param;
 393         char buf[256];
 394         char *str;
 395 
 396         if (expr->type != EXPR_ASSIGNMENT || expr->op != '=')
 397                 return false;
 398         left = expr->left;
 399         right = expr->right;
 400 
 401         while (right->type == EXPR_ASSIGNMENT)


 455          * is maybe (-4)-65531 but we know it is in the 0-65531 range so both
 456          * parts have to be considered.  We use _nomod() because it's not really
 457          * another modification, it's just a clarification.
 458          *
 459          */
 460         if (estate_rl(orig)) {
 461                 struct smatch_state *faked;
 462                 struct range_list *rl;
 463 
 464                 faked = get_extra_state(left);
 465                 if (estate_rl(faked)) {
 466                         rl = rl_intersection(estate_rl(faked), estate_rl(orig));
 467                         if (rl)
 468                                 set_extra_expr_nomod(expr, alloc_estate_rl(rl));
 469                 }
 470         }
 471 
 472         return true;
 473 }
 474 
 475 static void set_fresh_mtag_returns(struct db_callback_info *db_info)
 476 {
 477         struct expression *expr = db_info->expr->left;
 478         struct smatch_state *state;
 479 
 480         if (!db_info->ret_state)
 481                 return;
 482 
 483         state = alloc_estate_rl(cast_rl(get_type(expr), clone_rl(estate_rl(db_info->ret_state))));
 484         state = get_mtag_return(db_info->expr, state);
 485         if (!state)
 486                 return;
 487 
 488         set_real_absolute(expr, state);
 489         set_extra_expr_mod(expr, state);
 490 
 491         db_info->ret_state = NULL;
 492         db_info->ret_str = NULL;
 493 }
 494 
 495 static void set_return_assign_state(struct db_callback_info *db_info)
 496 {
 497         struct expression *expr = db_info->expr->left;
 498         struct smatch_state *state;
 499 
 500         if (!db_info->ret_state)
 501                 return;
 502 
 503         state = alloc_estate_rl(cast_rl(get_type(expr), clone_rl(estate_rl(db_info->ret_state))));
 504         if (!fake_a_param_assignment(db_info->expr, db_info->ret_str, state))
 505                 set_extra_expr_mod(expr, state);
 506 
 507         db_info->ret_state = NULL;
 508         db_info->ret_str = NULL;
 509 }
 510 
 511 static void set_other_side_state(struct db_callback_info *db_info)
 512 {
 513         struct expression *expr = db_info->var_expr;
 514         struct smatch_state *state;


 650         int type, param;
 651         char *ret_str, *key, *value;
 652         struct return_implies_callback *tmp;
 653         struct stree *stree;
 654         int return_id;
 655         int comparison;
 656 
 657         if (argc != 6)
 658                 return 0;
 659 
 660         return_id = atoi(argv[0]);
 661         ret_str = argv[1];
 662         type = atoi(argv[2]);
 663         param = atoi(argv[3]);
 664         key = argv[4];
 665         value = argv[5];
 666 
 667         db_info->has_states = 1;
 668         if (db_info->prev_return_id != -1 && type == INTERNAL) {
 669                 set_other_side_state(db_info);
 670                 set_implied_states(db_info);
 671                 stree = __pop_fake_cur_stree();

 672                 if (!db_info->cull)
 673                         merge_fake_stree(&db_info->stree, stree);
 674                 free_stree(&stree);
 675                 __push_fake_cur_stree();
 676                 db_info->cull = 0;
 677         }
 678         db_info->prev_return_id = return_id;
 679 
 680         if (type == INTERNAL && func_type_mismatch(db_info->expr, value))
 681                 db_info->cull = 1;
 682         if (db_info->cull)
 683                 return 0;
 684         if (type == CULL_PATH) {
 685                 db_info->cull = 1;
 686                 return 0;
 687         }
 688 
 689         if (is_impossible_data(type, db_info->expr, param, key, value)) {
 690                 db_info->cull = 1;
 691                 return 0;
 692         }
 693 
 694         call_results_to_rl(db_info->expr, get_type(strip_expr(db_info->expr)), ret_str, &ret_range);
 695         ret_range = cast_rl(get_type(db_info->expr), ret_range);
 696         if (!ret_range)
 697                 ret_range = alloc_whole_rl(get_type(db_info->expr));
 698 
 699         comparison = db_info->comparison;
 700         if (db_info->left)
 701                 comparison = flip_comparison(comparison);
 702 
 703         if (db_info->true_side) {
 704                 if (!possibly_true_rl(var_rl, comparison, ret_range))
 705                         return 0;
 706                 if (type == PARAM_LIMIT)
 707                         param_limit_implications(db_info->expr, param, key, value, &db_info->implied);
 708                 filter_by_comparison(&var_rl, comparison, ret_range);
 709                 filter_by_comparison(&ret_range, flip_comparison(comparison), var_rl);
 710         } else {
 711                 if (!possibly_false_rl(var_rl, comparison, ret_range))
 712                         return 0;
 713                 if (type == PARAM_LIMIT)
 714                         param_limit_implications(db_info->expr, param, key, value, &db_info->implied);
 715                 filter_by_comparison(&var_rl, negate_comparison(comparison), ret_range);
 716                 filter_by_comparison(&ret_range, flip_comparison(negate_comparison(comparison)), var_rl);
 717         }
 718 
 719         handle_ret_equals_param(ret_str, ret_range, db_info->expr);
 720 
 721         if (type == INTERNAL) {
 722                 set_state(-1, "unnull_path", NULL, &true_state);
 723                 __add_return_comparison(strip_expr(db_info->expr), ret_str);
 724                 __add_return_to_param_mapping(db_info->expr, ret_str);
 725                 store_return_state(db_info, ret_str, alloc_estate_rl(clone_rl(var_rl)));
 726         }
 727 
 728         FOR_EACH_PTR(db_info->callbacks, tmp) {
 729                 if (tmp->type == type)
 730                         tmp->callback(db_info->expr, param, key, value);
 731         } END_FOR_EACH_PTR(tmp);
 732 
 733         return 0;
 734 }


 759         }
 760 
 761         get_absolute_rl(var_expr, &rl);
 762 
 763         db_info.comparison = comparison;
 764         db_info.expr = call_expr;
 765         db_info.rl = rl;
 766         db_info.left = call_on_left;
 767         db_info.callbacks = db_return_states_list;
 768         db_info.var_expr = var_expr;
 769 
 770         call_return_states_before_hooks();
 771 
 772         db_info.true_side = 1;
 773         db_info.stree = NULL;
 774         db_info.prev_return_id = -1;
 775         __push_fake_cur_stree();
 776         sql_select_return_states("return_id, return, type, parameter, key, value",
 777                                  call_expr, db_compare_callback, &db_info);
 778         set_other_side_state(&db_info);
 779         set_implied_states(&db_info);
 780         stree = __pop_fake_cur_stree();
 781         if (!db_info.cull)
 782                 merge_fake_stree(&db_info.stree, stree);
 783         free_stree(&stree);
 784         true_states = db_info.stree;
 785         if (!true_states && db_info.has_states) {
 786                 __push_fake_cur_stree();
 787                 set_path_impossible();
 788                 true_states = __pop_fake_cur_stree();
 789         }
 790 
 791         nullify_path();
 792         __unnullify_path();
 793         FOR_EACH_SM(orig_states, sm) {
 794                 __set_sm_cur_stree(sm);
 795         } END_FOR_EACH_SM(sm);
 796 
 797         db_info.true_side = 0;
 798         db_info.stree = NULL;
 799         db_info.prev_return_id = -1;
 800         db_info.cull = 0;
 801         __push_fake_cur_stree();
 802         sql_select_return_states("return_id, return, type, parameter, key, value", call_expr,
 803                         db_compare_callback, &db_info);
 804         set_other_side_state(&db_info);
 805         set_implied_states(&db_info);
 806         stree = __pop_fake_cur_stree();
 807         if (!db_info.cull)
 808                 merge_fake_stree(&db_info.stree, stree);
 809         free_stree(&stree);
 810         false_states = db_info.stree;
 811         if (!false_states && db_info.has_states) {
 812                 __push_fake_cur_stree();
 813                 set_path_impossible();
 814                 false_states = __pop_fake_cur_stree();
 815         }
 816 
 817         nullify_path();
 818         __unnullify_path();
 819         FOR_EACH_SM(orig_states, sm) {
 820                 __set_sm_cur_stree(sm);
 821         } END_FOR_EACH_SM(sm);
 822 
 823         free_stree(&orig_states);
 824 
 825         FOR_EACH_SM(true_states, sm) {


 910         struct range_list *ret_range;
 911         int type, param;
 912         char *ret_str, *key, *value;
 913         struct return_implies_callback *tmp;
 914         struct stree *stree;
 915         int return_id;
 916 
 917         if (argc != 6)
 918                 return 0;
 919 
 920         return_id = atoi(argv[0]);
 921         ret_str = argv[1];
 922         type = atoi(argv[2]);
 923         param = atoi(argv[3]);
 924         key = argv[4];
 925         value = argv[5];
 926 
 927         if (db_info->prev_return_id != -1 && type == INTERNAL) {
 928                 call_ranged_return_hooks(db_info);
 929                 set_return_assign_state(db_info);
 930                 set_implied_states(db_info);
 931                 stree = __pop_fake_cur_stree();
 932                 if (!db_info->cull)
 933                         merge_fake_stree(&db_info->stree, stree);
 934                 free_stree(&stree);
 935                 __push_fake_cur_stree();
 936                 db_info->cull = 0;
 937         }
 938         db_info->prev_return_id = return_id;
 939 
 940         if (type == INTERNAL && func_type_mismatch(db_info->expr, value))
 941                 db_info->cull = 1;
 942         if (db_info->cull)
 943                 return 0;
 944         if (type == CULL_PATH) {
 945                 db_info->cull = 1;
 946                 return 0;
 947         }
 948         if (is_impossible_data(type, db_info->expr, param, key, value)) {
 949                 db_info->cull = 1;
 950                 return 0;
 951         }
 952 
 953         if (type == PARAM_LIMIT)
 954                 param_limit_implications(db_info->expr, param, key, value, &db_info->implied);
 955 
 956         db_info->handled = 1;
 957         call_results_to_rl(db_info->expr->right, get_type(strip_expr(db_info->expr->right)), ret_str, &ret_range);
 958         if (!ret_range)
 959                 ret_range = alloc_whole_rl(get_type(strip_expr(db_info->expr->right)));
 960         ret_range = cast_rl(get_type(db_info->expr->right), ret_range);
 961 
 962         if (type == INTERNAL) {
 963                 set_state(-1, "unnull_path", NULL, &true_state);
 964                 __add_return_comparison(strip_expr(db_info->expr->right), ret_str);
 965                 __add_comparison_info(db_info->expr->left, strip_expr(db_info->expr->right), ret_str);
 966                 __add_return_to_param_mapping(db_info->expr, ret_str);
 967                 store_return_state(db_info, ret_str, alloc_estate_rl(ret_range));
 968                 set_fresh_mtag_returns(db_info);
 969         }
 970 
 971         FOR_EACH_PTR(db_return_states_list, tmp) {
 972                 if (tmp->type == type)
 973                         tmp->callback(db_info->expr, param, key, value);
 974         } END_FOR_EACH_PTR(tmp);
 975 
 976         return 0;
 977 }
 978 
 979 static int db_return_states_assign(struct expression *expr)
 980 {
 981         struct expression *right;
 982         struct sm_state *sm;
 983         struct stree *stree;
 984         struct db_callback_info db_info = {};
 985 
 986         right = strip_expr(expr->right);
 987 
 988         db_info.prev_return_id = -1;
 989         db_info.expr = expr;
 990         db_info.stree = NULL;
 991         db_info.handled = 0;
 992 
 993         call_return_states_before_hooks();
 994 
 995         __push_fake_cur_stree();
 996         sql_select_return_states("return_id, return, type, parameter, key, value",
 997                         right, db_assign_return_states_callback, &db_info);
 998         if (option_debug) {
 999                 sm_msg("%s return_id %d return_ranges %s",
1000                         db_info.cull ? "culled" : "merging",
1001                         db_info.prev_return_id,
1002                         db_info.ret_state ? db_info.ret_state->name : "'<empty>'");
1003         }
1004         if (db_info.handled)
1005                 call_ranged_return_hooks(&db_info);
1006         set_return_assign_state(&db_info);
1007         set_implied_states(&db_info);
1008         stree = __pop_fake_cur_stree();
1009         if (!db_info.cull)
1010                 merge_fake_stree(&db_info.stree, stree);
1011         free_stree(&stree);
1012 
1013         if (!db_info.stree && db_info.cull) { /* this means we culled everything */
1014                 set_extra_expr_mod(expr->left, alloc_estate_whole(get_type(expr->left)));
1015                 set_path_impossible();
1016         }
1017         FOR_EACH_SM(db_info.stree, sm) {
1018                 __set_sm(sm);
1019         } END_FOR_EACH_SM(sm);
1020 
1021         free_stree(&db_info.stree);
1022         call_return_states_after_hooks(right);
1023 
1024         return db_info.handled;
1025 }
1026 
1027 static int handle_implied_return(struct expression *expr)


1099         struct range_list *ret_range;
1100         int type, param;
1101         char *ret_str, *key, *value;
1102         struct return_implies_callback *tmp;
1103         struct stree *stree;
1104         int return_id;
1105         char buf[64];
1106 
1107         if (argc != 6)
1108                 return 0;
1109 
1110         return_id = atoi(argv[0]);
1111         ret_str = argv[1];
1112         type = atoi(argv[2]);
1113         param = atoi(argv[3]);
1114         key = argv[4];
1115         value = argv[5];
1116 
1117         if (db_info->prev_return_id != -1 && type == INTERNAL) {
1118                 call_ranged_return_hooks(db_info);
1119                 set_implied_states(db_info);
1120                 stree = __pop_fake_cur_stree();
1121                 if (!db_info->cull)
1122                         merge_fake_stree(&db_info->stree, stree);
1123                 free_stree(&stree);
1124                 __push_fake_cur_stree();
1125                 __unnullify_path();
1126                 db_info->cull = 0;
1127         }
1128         db_info->prev_return_id = return_id;
1129 
1130         if (type == INTERNAL && func_type_mismatch(db_info->expr, value))
1131                 db_info->cull = 1;
1132         if (db_info->cull)
1133                 return 0;
1134         if (type == CULL_PATH) {
1135                 db_info->cull = 1;
1136                 return 0;
1137         }
1138         if (is_impossible_data(type, db_info->expr, param, key, value)) {
1139                 db_info->cull = 1;
1140                 return 0;
1141         }
1142 
1143         if (type == PARAM_LIMIT)
1144                 param_limit_implications(db_info->expr, param, key, value, &db_info->implied);
1145 
1146         call_results_to_rl(db_info->expr, get_type(strip_expr(db_info->expr)), ret_str, &ret_range);
1147         ret_range = cast_rl(get_type(db_info->expr), ret_range);
1148 
1149         if (type == INTERNAL) {
1150                 struct smatch_state *state;
1151 
1152                 set_state(-1, "unnull_path", NULL, &true_state);
1153                 __add_return_comparison(strip_expr(db_info->expr), ret_str);
1154                 __add_return_to_param_mapping(db_info->expr, ret_str);
1155                 /*
1156                  * We want to store the return values so that we can split the strees
1157                  * in smatch_db.c.  This uses set_state() directly because it's not a
1158                  * real smatch_extra state.
1159                  */
1160                 snprintf(buf, sizeof(buf), "return %p", db_info->expr);
1161                 state = alloc_estate_rl(ret_range);
1162                 set_state(SMATCH_EXTRA, buf, NULL, state);
1163                 store_return_state(db_info, ret_str, state);
1164         }


1175 static void db_return_states(struct expression *expr)
1176 {
1177         struct sm_state *sm;
1178         struct stree *stree;
1179         struct db_callback_info db_info = {};
1180 
1181         if (!__get_cur_stree())  /* no return functions */
1182                 return;
1183 
1184         db_info.prev_return_id = -1;
1185         db_info.expr = expr;
1186         db_info.stree = NULL;
1187 
1188         call_return_states_before_hooks();
1189 
1190         __push_fake_cur_stree();
1191         __unnullify_path();
1192         sql_select_return_states("return_id, return, type, parameter, key, value",
1193                         expr, db_return_states_callback, &db_info);
1194         call_ranged_return_hooks(&db_info);
1195         set_implied_states(&db_info);
1196         stree = __pop_fake_cur_stree();
1197         if (!db_info.cull)
1198                 merge_fake_stree(&db_info.stree, stree);
1199         free_stree(&stree);
1200 
1201         FOR_EACH_SM(db_info.stree, sm) {
1202                 __set_sm(sm);
1203         } END_FOR_EACH_SM(sm);
1204 
1205         free_stree(&db_info.stree);
1206         call_return_states_after_hooks(expr);
1207 }
1208 
1209 static int is_condition_call(struct expression *expr)
1210 {
1211         struct expression *tmp;
1212 
1213         FOR_EACH_PTR_REVERSE(big_condition_stack, tmp) {
1214                 if (expr == tmp || expr_get_parent_expr(expr) == tmp)
1215                         return 1;