Print this page
11506 smatch resync
*** 245,254 ****
--- 245,286 ----
if (get_terminated_state(expr) == &terminated)
return 1;
return 0;
}
+ static void match_strnlen_test(struct expression *expr)
+ {
+ struct expression *left, *tmp, *arg;
+ int cnt;
+
+ if (expr->type != EXPR_COMPARE)
+ return;
+ if (expr->op != SPECIAL_EQUAL && expr->op != SPECIAL_NOTEQUAL)
+ return;
+
+ left = strip_expr(expr->left);
+ cnt = 0;
+ while ((tmp = get_assigned_expr(left))) {
+ if (cnt++ > 3)
+ break;
+ left = tmp;
+ }
+
+ if (left->type != EXPR_CALL)
+ return;
+ if (!sym_name_is("strnlen", left->fn))
+ return;
+ arg = get_argument_from_call_expr(left->args, 0);
+ set_true_false_states_expr(my_id, arg,
+ (expr->op == SPECIAL_EQUAL) ? &terminated : NULL,
+ (expr->op == SPECIAL_NOTEQUAL) ? &terminated : NULL);
+ if (get_param_num(arg) >= 0)
+ set_true_false_states_expr(param_set_id, arg,
+ (expr->op == SPECIAL_EQUAL) ? &terminated : NULL,
+ (expr->op == SPECIAL_NOTEQUAL) ? &terminated : NULL);
+ }
+
void register_nul_terminator(int id)
{
my_id = id;
add_hook(&match_nul_assign, ASSIGNMENT_HOOK);
*** 258,267 ****
--- 290,301 ----
add_member_info_callback(my_id, struct_member_callback);
add_split_return_callback(&split_return_info);
select_caller_info_hook(caller_info_terminated, TERMINATED);
select_return_states_hook(TERMINATED, return_info_terminated);
+
+ add_hook(&match_strnlen_test, CONDITION_HOOK);
}
void register_nul_terminator_param_set(int id)
{
param_set_id = id;