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;