On Thu, Jul 21, 2022 at 12:30:32PM +0200, Christophe JAILLET wrote: > You could add find_last_bit(), find_next_zero_bit_le() and > find_next_bit_le(). > Thanks! > > > > regards, > > dan carpenter > > > > > > A reduced version of mine was: > > @@ > expression e1, e2; > statement S; > @@ > ( > * e1 = find_first_bit(...); > | > * e1 = find_last_bit(...); > | > [... snip ...] > ) > ... > if (e1 > e2) > S > > > (and it takes only a few seconds to scan the whole kernel :) ) Nice! I wasn't going to be before but now I have to re-write my generic check to be even more *powerful* than before! The new check doesn't rely on known values for the limit, but uses comparison data instead. (Still takes overnight to run so I might end up sorely dissappointed and defeated tomorrow morning) regards, dan carpenter
/* * Copyright (C) 2022 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_extra.h" static int my_id; static void match_condition(struct expression *expr) { struct expression *prev; int comparison; sval_t sval; char *name; if (expr->type != EXPR_COMPARE) return; if (expr->op != '>' && expr->op != SPECIAL_UNSIGNED_GT) return; if (!get_implied_value(expr, &sval) || sval.value != 0) return; comparison = get_comparison(expr->left, expr->right); if (!comparison) return; if (show_special(comparison)[1] != '=') return; prev = get_assigned_expr(expr->left); prev = strip_expr(prev); if (!prev || prev->type != EXPR_CALL) return; name = expr_to_str(prev->fn); sm_warning("potential off by one check '%s()'", name); free_string(name); } void check_off_by_one_capped_return(int id) { my_id = id; add_hook(&match_condition, CONDITION_HOOK); }