/* * Copyright (C) 2023 Dan Carpenter. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt */ #include "smatch.h" #include "smatch_slist.h" #include "smatch_extra.h" static int my_id; static struct expression *get_len_expr(struct expression *expr) { struct expression *deref; if (expr->type != EXPR_DEREF) return NULL; deref = strip_expr(expr->deref); if (local_debug) sm_msg("%s: expr='%s' op='%c'", __func__, expr_to_str(expr), expr->op); return gen_expression_from_key(deref, (expr->op == '.') ? "$.len" : "$->len"); } static void array_check(struct expression *expr) { struct expression *array_expr, *offset, *len; char *member, *name; int comparison; expr = strip_expr(expr); array_expr = get_array_base(expr); offset = get_array_offset(expr); if (!array_expr || !offset) return; member = get_member_name(array_expr); if (!member || strcmp(member, "(struct i2c_msg)->buf") != 0) goto free; len = get_len_expr(array_expr); if (!len) goto free; comparison = get_comparison(offset, len); if (comparison == '<') goto free; name = expr_to_str(len); sm_warning("i2c_msg ->buf not checked '%s'", name); free_string(name); free: free_string(member); } void check_i2c_msg_buf(int id) { my_id = id; if (option_project != PROJ_KERNEL) return; add_hook(&array_check, OP_HOOK); }