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
20 #include "smatch_extra.h"
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
);
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
);
41 case SPECIAL_UNSIGNED_LT
:
42 case SPECIAL_UNSIGNED_LTE
:
43 *left
= strip_parens(expr
->left
);
45 *right
= strip_parens(expr
->right
);
52 static bool is_upper(struct expression
*var
, struct expression
*cond
)
54 struct expression
*left
, *right
;
57 cond
= strip_expr(cond
);
59 if (!flip_order(cond
, &left
, &op
, &right
))
61 if (expr_equiv(var
, right
))
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
)
73 if (is_upper(var
, stmt
->if_conditional
))
76 else_cond
= stmt
->if_false
;
77 if (!else_cond
|| else_cond
->type
!= STMT_IF
)
79 if (is_upper(var
, else_cond
->if_conditional
))
85 static bool is_allowed_zero(struct expression
*expr
)
89 macro
= get_macro_name(expr
->pos
);
92 if (strcmp(macro
, "ARRAY_SIZE") == 0 ||
93 strcmp(macro
, "DPMCP_MIN_VER_MINOR") == 0 ||
94 strcmp(macro
, "KASAN_SHADOW_OFFSET") == 0 ||
95 strcmp(macro
, "NF_CT_HELPER_BUILD_BUG_ON") == 0 ||
96 strcmp(macro
, "TEST_ONE_SHIFT") == 0)
101 static bool has_upper_bound(struct expression
*var
, struct expression
*expr
)
103 struct expression
*parent
, *prev
;
107 while ((parent
= expr_get_parent_expr(parent
))) {
108 if (parent
->type
== EXPR_LOGICAL
&&
109 parent
->op
== SPECIAL_LOGICAL_AND
)
111 if (parent
->type
== EXPR_LOGICAL
&&
112 parent
->op
== SPECIAL_LOGICAL_OR
) {
113 if (prev
== parent
->left
&&
114 is_upper(var
, parent
->right
))
116 if (prev
== parent
->right
&&
117 is_upper(var
, parent
->left
))
122 if (is_if_else_clamp_stmt(var
, prev
))
128 static void match_condition(struct expression
*expr
)
130 struct expression
*left
, *right
;
134 if (expr
->type
!= EXPR_COMPARE
)
137 if (!flip_order(expr
, &left
, &op
, &right
))
141 op
!= SPECIAL_UNSIGNED_LT
)
144 if (!expr_is_zero(right
))
147 if (is_allowed_zero(right
))
150 if (op
!= SPECIAL_UNSIGNED_LT
&& !expr_unsigned(left
))
153 if (has_upper_bound(left
, expr
))
156 name
= expr_to_str(left
);
157 sm_warning("unsigned '%s' is never less than zero.", name
);
161 void check_unsigned_lt_zero(int id
)
165 add_hook(&match_condition
, CONDITION_HOOK
);