Skip to content

Commit 867046c

Browse files
david-laightakpm00
authored andcommitted
minmax: relax check to allow comparison between unsigned arguments and signed constants
Allow (for example) min(unsigned_var, 20). The opposite min(signed_var, 20u) is still errored. Since a comparison between signed and unsigned never makes the unsigned value negative it is only necessary to adjust the __types_ok() test. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: David Laight <[email protected]> Cc: Andy Shevchenko <[email protected]> Cc: Christoph Hellwig <[email protected]> Cc: Jason A. Donenfeld <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Matthew Wilcox (Oracle) <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 4ead534 commit 867046c

File tree

1 file changed

+17
-7
lines changed

1 file changed

+17
-7
lines changed

include/linux/minmax.h

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,18 @@
1010
/*
1111
* min()/max()/clamp() macros must accomplish three things:
1212
*
13-
* - avoid multiple evaluations of the arguments (so side-effects like
13+
* - Avoid multiple evaluations of the arguments (so side-effects like
1414
* "x++" happen only once) when non-constant.
15-
* - perform signed v unsigned type-checking (to generate compile
16-
* errors instead of nasty runtime surprises).
17-
* - retain result as a constant expressions when called with only
15+
* - Retain result as a constant expressions when called with only
1816
* constant expressions (to avoid tripping VLA warnings in stack
1917
* allocation usage).
18+
* - Perform signed v unsigned type-checking (to generate compile
19+
* errors instead of nasty runtime surprises).
20+
* - Unsigned char/short are always promoted to signed int and can be
21+
* compared against signed or unsigned arguments.
22+
* - Unsigned arguments can be compared against non-negative signed constants.
23+
* - Comparison of a signed argument against an unsigned constant fails
24+
* even if the constant is below __INT_MAX__ and could be cast to int.
2025
*/
2126
#define __typecheck(x, y) \
2227
(!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
@@ -26,9 +31,14 @@
2631
__builtin_choose_expr(__is_constexpr(is_signed_type(typeof(x))), \
2732
is_signed_type(typeof(x)), 0)
2833

29-
#define __types_ok(x, y) \
30-
(__is_signed(x) == __is_signed(y) || \
31-
__is_signed((x) + 0) == __is_signed((y) + 0))
34+
/* True for a non-negative signed int constant */
35+
#define __is_noneg_int(x) \
36+
(__builtin_choose_expr(__is_constexpr(x) && __is_signed(x), x, -1) >= 0)
37+
38+
#define __types_ok(x, y) \
39+
(__is_signed(x) == __is_signed(y) || \
40+
__is_signed((x) + 0) == __is_signed((y) + 0) || \
41+
__is_noneg_int(x) || __is_noneg_int(y))
3242

3343
#define __cmp_op_min <
3444
#define __cmp_op_max >

0 commit comments

Comments
 (0)