Print this page
11506 smatch resync
@@ -245,10 +245,42 @@
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,10 +290,12 @@
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;