do{} while(n--) loops end at n=-1 but programmers sometimes assume that they end at n=0. This checker sends a warning in these scenarios. Signed-off-by: Harshvardhan Jha <harshvardhan.jha@xxxxxxxxxx> --- check_do_while_loop_limit.c | 67 +++++++++++++++++++++++++++++++++++++ check_list.h | 1 + 2 files changed, 68 insertions(+) create mode 100644 check_do_while_loop_limit.c diff --git a/check_do_while_loop_limit.c b/check_do_while_loop_limit.c new file mode 100644 index 00000000..cc04dfa5 --- /dev/null +++ b/check_do_while_loop_limit.c @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2021 Oracle. + * + * 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; + +STATE(post_minus); + +static bool is_post_minus(struct expression *expr) +{ + expr = strip_expr(expr); + if (!expr) + return false; + if (expr->type != EXPR_POSTOP) + return false; + if (expr->op != SPECIAL_DECREMENT) + return false; + return true; +} + +static void match_post_loop(struct expression *expr) +{ + struct statement *stmt; + + expr = strip_expr(expr); + stmt = expr_get_parent_stmt(expr); + + if (!stmt) + return; + if (stmt->type != STMT_ITERATOR) + return; + if (!is_post_minus(stmt->iterator_post_condition)) + return; + if (is_post_minus(stmt->iterator_post_condition)) + set_state_expr(my_id, stmt->iterator_post_condition->left, &post_minus); +} + +static void match_condition(struct expression *expr) +{ + if (get_state_expr(my_id, expr) != &post_minus) + return; + sm_warning("do while ends on '%s == -1'", expr_to_str(expr)); +} + +void check_do_while_loop_limit(int id) +{ + my_id = id; + add_hook(&match_post_loop, CONDITION_HOOK); + add_hook(&match_condition, CONDITION_HOOK); +} diff --git a/check_list.h b/check_list.h index a57715ea..4d18a173 100644 --- a/check_list.h +++ b/check_list.h @@ -171,6 +171,7 @@ CK(check_syscall_arg_type) CK(check_trinity_generator) CK(register_param_bits_set) CK(register_param_bits_clear) +CK(check_do_while_loop_limit) /* <- your test goes here */ /* CK(register_template) */ -- 2.32.0