From f0a6644ddc8d5a3c34c6892fd69259c2892963d3 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 22 Mar 2010 21:37:06 +0300 Subject: [PATCH] *new* check_resource_size(): prod people to use resource_size() There is a kernel function called resource_size() and this check encourages people to use it. Normally people calculate their resource size by doing "end - start" but the correct way is to do "end - start + 1". This check produces at least two false positives: netxen has an end which is 1 higher than normal so end - start works. some other driver does "size - 3" depending on the config. But generally this check works surprisingly well. Signed-off-by: Dan Carpenter --- check_list.h | 1 + check_resource_size.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 check_resource_size.c diff --git a/check_list.h b/check_list.h index df88e826..8ef4b1c8 100644 --- a/check_list.h +++ b/check_list.h @@ -37,6 +37,7 @@ CK(check_no_return) CK(check_mod_timer) CK(check_le16) CK(check_return) +CK(check_resource_size) /* <- your test goes here */ /* CK(register_template) */ diff --git a/check_resource_size.c b/check_resource_size.c new file mode 100644 index 00000000..83c06bc2 --- /dev/null +++ b/check_resource_size.c @@ -0,0 +1,79 @@ +/* + * smatch/check_resource_size.c + * + * Copyright (C) 2010 Dan Carpenter. + * + * Licensed under the Open Software License version 1.1 + * + */ + +#include "smatch.h" + +static int my_id; +extern int check_assigned_expr_id; + +static int is_probably_ok(struct expression *expr) +{ + expr = strip_expr(expr); + + if (expr->type == EXPR_BINOP) + return 1; + if (expr->type == EXPR_SIZEOF) + return 1; + + return 0; +} + +static void verify_size_expr(struct expression *expr) +{ + if (expr->type != EXPR_BINOP) + return; + if (expr->op != '-') + return; + if (is_probably_ok(expr->left)) + return; + if (is_probably_ok(expr->right)) + return; + sm_msg("warn: consider using resource_size() here"); +} + +static void handle_assigned_expr(struct expression *expr) +{ + struct smatch_state *state; + + state = get_state_expr(check_assigned_expr_id, expr); + if (!state || !state->data) + return; + expr = (struct expression *)state->data; + verify_size_expr(expr); +} + +static void match_resource(const char *fn, struct expression *expr, void *_arg_no) +{ + struct expression *arg_expr; + int arg_no = (int)_arg_no; + + arg_expr = get_argument_from_call_expr(expr->args, arg_no); + arg_expr = strip_expr(arg_expr); + + if (arg_expr->type == EXPR_SYMBOL) { + handle_assigned_expr(arg_expr); + return; + } + verify_size_expr(arg_expr); +} + +void check_resource_size(int id) +{ + my_id = id; + + if (option_project != PROJ_KERNEL) + return; + + add_function_hook("ioremap_nocache", &match_resource, (void *)1); + add_function_hook("ioremap", &match_resource, (void *)1); + add_function_hook("__request_region", &match_resource, (void *)2); + add_function_hook("__release_region", &match_resource, (void *)2); + add_function_hook("__devm_request_region", &match_resource, (void *)3); + add_function_hook("__devm_release_region", &match_resource, (void *)3); +} -- 2.11.4.GIT