db/fixup_kernel.sh: no user data is passed to suspend/resume
[smatch.git] / check_unsigned_lt_zero.c
blobc1604e080551d0bb5211b33d8b1d8f9ff2b19205
1 /*
2 * Copyright (C) 2009 Dan Carpenter.
3 * Copyright 2023 Linaro Ltd.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
19 #include "smatch.h"
20 #include "smatch_extra.h"
22 static int my_id;
24 static bool flip_order(struct expression *expr, struct expression **left, int *op, struct expression **right)
26 /* flip everything to < */
28 expr = strip_expr(expr);
30 switch (expr->op) {
31 case '>':
32 case SPECIAL_GTE:
33 case SPECIAL_UNSIGNED_GT:
34 case SPECIAL_UNSIGNED_GTE:
35 *left = strip_parens(expr->right);
36 *op = flip_comparison(expr->op);
37 *right = strip_parens(expr->left);
38 return true;
39 case '<':
40 case SPECIAL_LTE:
41 case SPECIAL_UNSIGNED_LT:
42 case SPECIAL_UNSIGNED_LTE:
43 *left = strip_parens(expr->left);
44 *op = expr->op;
45 *right = strip_parens(expr->right);
46 return true;
49 return false;
52 static bool is_upper(struct expression *var, struct expression *cond)
54 struct expression *left, *right;
55 int op;
57 cond = strip_expr(cond);
59 if (!flip_order(cond, &left, &op, &right))
60 return false;
61 if (expr_equiv(var, right))
62 return true;
63 return false;
66 static bool is_if_else_clamp_stmt(struct expression *var, struct expression *expr)
68 struct statement *stmt, *else_cond;
70 stmt = expr_get_parent_stmt(expr);
71 if (!stmt || stmt->type != STMT_IF)
72 return false;
73 if (is_upper(var, stmt->if_conditional))
74 return true;
76 else_cond = stmt->if_false;
77 if (!else_cond || else_cond->type != STMT_IF)
78 return false;
79 if (is_upper(var, else_cond->if_conditional))
80 return true;
82 return false;
85 static bool is_allowed_zero(struct expression *expr)
87 char *macro;
89 macro = get_macro_name(expr->pos);
90 if (!macro)
91 return false;
92 if (strcmp(macro, "ARRAY_SIZE") == 0 ||
93 strcmp(macro, "DPMCP_MIN_VER_MINOR") == 0 ||
94 strcmp(macro, "KASAN_SHADOW_OFFSET") == 0)
95 return true;
96 return false;
99 static bool has_upper_bound(struct expression *var, struct expression *expr)
101 struct expression *parent, *prev;
103 parent = expr;
104 prev = expr;
105 while ((parent = expr_get_parent_expr(parent))) {
106 if (parent->type == EXPR_LOGICAL &&
107 parent->op == SPECIAL_LOGICAL_AND)
108 break;
109 if (parent->type == EXPR_LOGICAL &&
110 parent->op == SPECIAL_LOGICAL_OR) {
111 if (prev == parent->left &&
112 is_upper(var, parent->right))
113 return true;
114 if (prev == parent->right &&
115 is_upper(var, parent->left))
116 return true;
118 prev = parent;
120 if (is_if_else_clamp_stmt(var, prev))
121 return true;
123 return false;
126 static void match_condition(struct expression *expr)
128 struct expression *left, *right;
129 char *name;
130 int op;
132 if (expr->type != EXPR_COMPARE)
133 return;
135 if (!flip_order(expr, &left, &op, &right))
136 return;
138 if (op != '<' &&
139 op != SPECIAL_UNSIGNED_LT)
140 return;
142 if (!expr_is_zero(right))
143 return;
145 if (is_allowed_zero(right))
146 return;
148 if (op != SPECIAL_UNSIGNED_LT && !expr_unsigned(left))
149 return;
151 if (has_upper_bound(left, expr))
152 return;
154 name = expr_to_str(left);
155 sm_warning("unsigned '%s' is never less than zero.", name);
156 free_string(name);
159 void check_unsigned_lt_zero(int id)
161 my_id = id;
163 add_hook(&match_condition, CONDITION_HOOK);