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;
|