GNU Linux-libre 6.1.90-gnu
[releases.git] / scripts / coccinelle / misc / do_div.cocci
1 // SPDX-License-Identifier: GPL-2.0-only
2 /// do_div() does a 64-by-32 division.
3 /// When the divisor is long, unsigned long, u64, or s64,
4 /// do_div() truncates it to 32 bits, this means it can test
5 /// non-zero and be truncated to 0 for division on 64bit platforms.
6 ///
7 //# This makes an effort to find those inappropriate do_div() calls.
8 //
9 // Confidence: Moderate
10 // Copyright: (C) 2020 Wen Yang, Alibaba.
11 // Comments:
12 // Options: --no-includes --include-headers
13
14 virtual context
15 virtual org
16 virtual report
17
18 @initialize:python@
19 @@
20
21 def get_digit_type_and_value(str):
22     is_digit = False
23     value = 0
24
25     try:
26         if (str.isdigit()):
27            is_digit = True
28            value =  int(str, 0)
29         elif (str.upper().endswith('ULL')):
30            is_digit = True
31            value = int(str[:-3], 0)
32         elif (str.upper().endswith('LL')):
33            is_digit = True
34            value = int(str[:-2], 0)
35         elif (str.upper().endswith('UL')):
36            is_digit = True
37            value = int(str[:-2], 0)
38         elif (str.upper().endswith('L')):
39            is_digit = True
40            value = int(str[:-1], 0)
41         elif (str.upper().endswith('U')):
42            is_digit = True
43            value = int(str[:-1], 0)
44     except Exception as e:
45           print('Error:',e)
46           is_digit = False
47           value = 0
48     finally:
49         return is_digit, value
50
51 def filter_out_safe_constants(str):
52     is_digit, value = get_digit_type_and_value(str)
53     if (is_digit):
54         if (value >= 0x100000000):
55             return True
56         else:
57             return False
58     else:
59         return True
60
61 def construct_warnings(suggested_fun):
62     msg="WARNING: do_div() does a 64-by-32 division, please consider using %s instead."
63     return  msg % suggested_fun
64
65 @depends on context@
66 expression f;
67 long l: script:python() { filter_out_safe_constants(l) };
68 unsigned long ul : script:python() { filter_out_safe_constants(ul) };
69 u64 ul64 : script:python() { filter_out_safe_constants(ul64) };
70 s64 sl64 : script:python() { filter_out_safe_constants(sl64) };
71
72 @@
73 (
74 * do_div(f, l);
75 |
76 * do_div(f, ul);
77 |
78 * do_div(f, ul64);
79 |
80 * do_div(f, sl64);
81 )
82
83 @r depends on (org || report)@
84 expression f;
85 position p;
86 long l: script:python() { filter_out_safe_constants(l) };
87 unsigned long ul : script:python() { filter_out_safe_constants(ul) };
88 u64 ul64 : script:python() { filter_out_safe_constants(ul64) };
89 s64 sl64 : script:python() { filter_out_safe_constants(sl64) };
90 @@
91 (
92 do_div@p(f, l);
93 |
94 do_div@p(f, ul);
95 |
96 do_div@p(f, ul64);
97 |
98 do_div@p(f, sl64);
99 )
100
101 @script:python depends on org@
102 p << r.p;
103 ul << r.ul;
104 @@
105
106 coccilib.org.print_todo(p[0], construct_warnings("div64_ul"))
107
108 @script:python depends on org@
109 p << r.p;
110 l << r.l;
111 @@
112
113 coccilib.org.print_todo(p[0], construct_warnings("div64_long"))
114
115 @script:python depends on org@
116 p << r.p;
117 ul64 << r.ul64;
118 @@
119
120 coccilib.org.print_todo(p[0], construct_warnings("div64_u64"))
121
122 @script:python depends on org@
123 p << r.p;
124 sl64 << r.sl64;
125 @@
126
127 coccilib.org.print_todo(p[0], construct_warnings("div64_s64"))
128
129 @script:python depends on report@
130 p << r.p;
131 ul << r.ul;
132 @@
133
134 coccilib.report.print_report(p[0], construct_warnings("div64_ul"))
135
136 @script:python depends on report@
137 p << r.p;
138 l << r.l;
139 @@
140
141 coccilib.report.print_report(p[0], construct_warnings("div64_long"))
142
143 @script:python depends on report@
144 p << r.p;
145 sl64 << r.sl64;
146 @@
147
148 coccilib.report.print_report(p[0], construct_warnings("div64_s64"))
149
150 @script:python depends on report@
151 p << r.p;
152 ul64 << r.ul64;
153 @@
154
155 coccilib.report.print_report(p[0], construct_warnings("div64_u64"))