For some reason this spits out an enourmous amount of false positives, making this entirely useless. We hit a lot of "%lx", (long)(a - b), but I don't understand why the a-b expression (a pointer difference) passes is_ptr_type(). Signed-off-by: Rasmus Villemoes <rv@xxxxxxxxxxxxxxxxxx> --- check_kernel_printf.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/check_kernel_printf.c b/check_kernel_printf.c index 87c6744a..b4a9dcde 100644 --- a/check_kernel_printf.c +++ b/check_kernel_printf.c @@ -939,6 +939,35 @@ static bool is_integer_specifier(int type) } } +static int +is_cast_expr(struct expression *expr) +{ + switch (expr->type) { + case EXPR_CAST: + case EXPR_FORCE_CAST: + /* not EXPR_IMPLIED_CAST for our purposes */ + return 1; + default: + return 0; + } +} + +static void +check_cast_from_pointer(const char *fmt, int len, struct expression *arg, int va_idx) +{ + /* + * This can easily be fooled by passing 0+(long)ptr or doing + * "long local_var = (long)ptr" and passing local_var to + * %lx. Tough. + */ + if (!is_cast_expr(arg)) + return; + while (is_cast_expr(arg)) + arg = arg->cast_expression; + if (is_ptr_type(get_type(arg))) + sm_msg("warn: argument %d to %.*s specifier is cast from pointer", + va_idx, len, fmt); +} static void do_check_printf_call(const char *caller, const char *name, struct expression *callexpr, struct expression *fmtexpr, int vaidx) @@ -1015,6 +1044,8 @@ do_check_printf_call(const char *caller, const char *name, struct expression *ca if (spec.base != 16 && has_hex_prefix(orig_fmt, old_fmt)) sm_msg("warn: '%.2s' prefix is confusing together with '%.*s' specifier", old_fmt-2, (int)(fmt-old_fmt), old_fmt); + + check_cast_from_pointer(old_fmt, read, arg, vaidx); } switch (spec.type) { -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe smatch" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html