2 * Copyright (C) 2022 Oracle.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
19 #include "smatch_extra.h"
20 #include "smatch_slist.h"
26 bool possible_err_ptr(struct expression
*expr
)
28 struct smatch_state
*state
;
29 struct range_list
*rl
;
31 state
= get_state_expr(SMATCH_EXTRA
, expr
);
32 if (state
&& estate_is_empty(state
))
35 get_absolute_rl(expr
, &rl
);
36 if (!rl_intersection(rl
, alloc_rl(ptr_err_min
, ptr_err_max
)))
38 if (!expr_has_possible_state(my_id
, expr
, &err_ptr
))
43 static void match_return_info(int return_id
, char *return_ranges
,
44 struct expression
*returned_expr
,
46 const char *printed_name
,
49 struct smatch_state
*state
;
51 if (param
!= -1 || strcmp(printed_name
, "$") != 0)
53 if (!slist_has_state(sm
->possible
, &err_ptr
))
56 state
= get_state(SMATCH_EXTRA
, sm
->name
, sm
->sym
);
59 if (!rl_intersection(estate_rl(state
), alloc_rl(ptr_err_min
, ptr_err_max
)))
62 sql_insert_return_states(return_id
, return_ranges
, ERR_PTR
, param
, printed_name
, "");
65 static void match_assign(struct expression
*expr
)
68 * I felt like I had to implement this function for completeness but
69 * also that it isn't required and might lead to false positives.
71 if (expr
->op
!= '=' || !is_pointer(expr
->left
))
73 if (!has_states(__get_cur_stree(), my_id
))
75 if (possible_err_ptr(expr
->right
))
76 set_state_expr(my_id
, expr
->left
, &err_ptr
);
79 static void match_err_ptr(const char *fn
, struct expression
*expr
, void *unused
)
81 set_state_expr(my_id
, expr
->left
, &err_ptr
);
84 static void set_error_code(struct expression
*expr
, const char *name
, struct symbol
*sym
, void *data
)
88 macro
= get_macro_name(expr
->pos
);
90 if (strcmp(macro
, "for_each_gpio_desc") == 0 ||
91 strcmp(macro
, "for_each_gpio_desc_with_flag") == 0)
95 set_state(my_id
, name
, sym
, &err_ptr
);
98 static void match_is_err_true(struct expression
*expr
, const char *name
, struct symbol
*sym
, void *data
)
100 set_state(my_id
, name
, sym
, &err_ptr
);
103 static void match_is_err_false(struct expression
*expr
, const char *name
, struct symbol
*sym
, void *data
)
105 set_state(my_id
, name
, sym
, &undefined
);
108 void register_kernel_err_ptr(int id
)
112 if (option_project
!= PROJ_KERNEL
)
115 add_modification_hook(my_id
, &set_undefined
);
116 add_hook(&match_assign
, ASSIGNMENT_HOOK
);
118 add_return_info_callback(my_id
, &match_return_info
);
120 add_function_assign_hook("ERR_PTR", &match_err_ptr
, NULL
);
121 add_function_assign_hook("ERR_CAST", &match_err_ptr
, NULL
);
122 return_implies_param_key_exact("IS_ERR", int_one
, int_one
,
123 match_is_err_true
, 0, "$", NULL
);
124 return_implies_param_key_exact("IS_ERR", int_zero
, int_zero
,
125 match_is_err_false
, 0, "$", NULL
);
126 return_implies_param_key_exact("PTR_ERR_OR_ZERO", ptr_err_min
, ptr_err_max
,
127 match_is_err_true
, 0, "$", NULL
);
128 return_implies_param_key_exact("PTR_ERR_OR_ZERO", int_zero
, int_zero
,
129 match_is_err_false
, 0, "$", NULL
);
130 return_implies_param_key_exact("IS_ERR_OR_NULL", int_zero
, int_zero
,
131 match_is_err_false
, 0, "$", NULL
);
132 select_return_param_key(ERR_PTR
, &set_error_code
);