Print this page
11506 smatch resync

@@ -443,10 +443,27 @@
         src = get_argument_from_call_expr(expr->args, 1);
 
         __struct_members_copy(COPY_MEMCPY, expr, remove_addr(dest), remove_addr(src));
 }
 
+static void match_memdup(const char *fn, struct expression *call_expr,
+                        struct expression *expr, void *_unused)
+{
+        struct expression *left, *right, *arg;
+
+        if (!expr || expr->type != EXPR_ASSIGNMENT)
+                return;
+
+        left = strip_expr(expr->left);
+        right = strip_expr(expr->right);
+
+        if (right->type != EXPR_CALL)
+                return;
+        arg = get_argument_from_call_expr(right->args, 0);
+        __struct_members_copy(COPY_MEMCPY, expr, left, arg);
+}
+
 static void match_memcpy_unknown(const char *fn, struct expression *expr, void *_arg)
 {
         struct expression *dest;
 
         dest = get_argument_from_call_expr(expr->args, 0);

@@ -546,10 +563,13 @@
         add_function_hook("memcpy", &match_memcpy, INT_PTR(0));
         add_function_hook("memmove", &match_memcpy, INT_PTR(0));
         add_function_hook("__memcpy", &match_memcpy, INT_PTR(0));
         add_function_hook("__memmove", &match_memcpy, INT_PTR(0));
 
+        if (option_project == PROJ_KERNEL)
+                return_implies_state_sval("kmemdup", valid_ptr_min_sval, valid_ptr_max_sval, &match_memdup, NULL);
+
         add_function_hook("sscanf", &match_sscanf, NULL);
 
         add_hook(&unop_expr, OP_HOOK);
         register_clears_param();
         select_return_states_hook(PARAM_CLEARED, &db_param_cleared);