1// SPDX-License-Identifier: GPL-2.0-only
2///
3/// Check for array_size(), array3_size(), struct_size() duplicates.
4/// These patterns are detected:
5///  1. An opencoded expression is used before array_size() to compute the same size
6///  2. An opencoded expression is used after array_size() to compute the same size
7/// From security point of view only first case is relevant. These functions
8/// perform arithmetic overflow check. Thus, if we use an opencoded expression
9/// before a call to the *_size() function we can miss an overflow.
10///
11// Confidence: High
12// Copyright: (C) 2020 Denis Efremov ISPRAS
13// Options: --no-includes --include-headers --no-loops
14
15virtual context
16virtual report
17virtual org
18
19@as@
20expression E1, E2;
21@@
22
23array_size(E1, E2)
24
25@as_next@
26expression subE1 <= as.E1;
27expression subE2 <= as.E2;
28expression as.E1, as.E2, E3;
29assignment operator aop;
30position p1, p2;
31@@
32
33* E1 * E2@p1
34  ... when != \(subE1\|subE2\) aop E3
35      when != &\(subE1\|subE2\)
36* array_size(E1, E2)@p2
37
38@script:python depends on report@
39p1 << as_next.p1;
40p2 << as_next.p2;
41@@
42
43msg = "WARNING: array_size is used later (line %s) to compute the same size" % (p2[0].line)
44coccilib.report.print_report(p1[0], msg)
45
46@script:python depends on org@
47p1 << as_next.p1;
48p2 << as_next.p2;
49@@
50
51msg = "WARNING: array_size is used later (line %s) to compute the same size" % (p2[0].line)
52coccilib.org.print_todo(p1[0], msg)
53
54@as_prev@
55expression subE1 <= as.E1;
56expression subE2 <= as.E2;
57expression as.E1, as.E2, E3;
58assignment operator aop;
59position p1, p2;
60@@
61
62* array_size(E1, E2)@p1
63  ... when != \(subE1\|subE2\) aop E3
64      when != &\(subE1\|subE2\)
65* E1 * E2@p2
66
67@script:python depends on report@
68p1 << as_prev.p1;
69p2 << as_prev.p2;
70@@
71
72msg = "WARNING: array_size is already used (line %s) to compute the same size" % (p1[0].line)
73coccilib.report.print_report(p2[0], msg)
74
75@script:python depends on org@
76p1 << as_prev.p1;
77p2 << as_prev.p2;
78@@
79
80msg = "WARNING: array_size is already used (line %s) to compute the same size" % (p1[0].line)
81coccilib.org.print_todo(p2[0], msg)
82
83@as3@
84expression E1, E2, E3;
85@@
86
87array3_size(E1, E2, E3)
88
89@as3_next@
90expression subE1 <= as3.E1;
91expression subE2 <= as3.E2;
92expression subE3 <= as3.E3;
93expression as3.E1, as3.E2, as3.E3, E4;
94assignment operator aop;
95position p1, p2;
96@@
97
98* E1 * E2 * E3@p1
99  ... when != \(subE1\|subE2\|subE3\) aop E4
100      when != &\(subE1\|subE2\|subE3\)
101* array3_size(E1, E2, E3)@p2
102
103@script:python depends on report@
104p1 << as3_next.p1;
105p2 << as3_next.p2;
106@@
107
108msg = "WARNING: array3_size is used later (line %s) to compute the same size" % (p2[0].line)
109coccilib.report.print_report(p1[0], msg)
110
111@script:python depends on org@
112p1 << as3_next.p1;
113p2 << as3_next.p2;
114@@
115
116msg = "WARNING: array3_size is used later (line %s) to compute the same size" % (p2[0].line)
117coccilib.org.print_todo(p1[0], msg)
118
119@as3_prev@
120expression subE1 <= as3.E1;
121expression subE2 <= as3.E2;
122expression subE3 <= as3.E3;
123expression as3.E1, as3.E2, as3.E3, E4;
124assignment operator aop;
125position p1, p2;
126@@
127
128* array3_size(E1, E2, E3)@p1
129  ... when != \(subE1\|subE2\|subE3\) aop E4
130      when != &\(subE1\|subE2\|subE3\)
131* E1 * E2 * E3@p2
132
133@script:python depends on report@
134p1 << as3_prev.p1;
135p2 << as3_prev.p2;
136@@
137
138msg = "WARNING: array3_size is already used (line %s) to compute the same size" % (p1[0].line)
139coccilib.report.print_report(p2[0], msg)
140
141@script:python depends on org@
142p1 << as3_prev.p1;
143p2 << as3_prev.p2;
144@@
145
146msg = "WARNING: array3_size is already used (line %s) to compute the same size" % (p1[0].line)
147coccilib.org.print_todo(p2[0], msg)
148
149@ss@
150expression E1, E2, E3;
151@@
152
153struct_size(E1, E2, E3)
154
155@ss_next@
156expression subE3 <= ss.E3;
157expression ss.E1, ss.E2, ss.E3, E4;
158assignment operator aop;
159position p1, p2;
160@@
161
162* E1 * E2 + E3@p1
163  ... when != subE3 aop E4
164      when != &subE3
165* struct_size(E1, E2, E3)@p2
166
167@script:python depends on report@
168p1 << ss_next.p1;
169p2 << ss_next.p2;
170@@
171
172msg = "WARNING: struct_size is used later (line %s) to compute the same size" % (p2[0].line)
173coccilib.report.print_report(p1[0], msg)
174
175@script:python depends on org@
176p1 << ss_next.p1;
177p2 << ss_next.p2;
178@@
179
180msg = "WARNING: struct_size is used later (line %s) to compute the same size" % (p2[0].line)
181coccilib.org.print_todo(p1[0], msg)
182
183@ss_prev@
184expression subE3 <= ss.E3;
185expression ss.E1, ss.E2, ss.E3, E4;
186assignment operator aop;
187position p1, p2;
188@@
189
190* struct_size(E1, E2, E3)@p1
191  ... when != subE3 aop E4
192      when != &subE3
193* E1 * E2 + E3@p2
194
195@script:python depends on report@
196p1 << ss_prev.p1;
197p2 << ss_prev.p2;
198@@
199
200msg = "WARNING: struct_size is already used (line %s) to compute the same size" % (p1[0].line)
201coccilib.report.print_report(p2[0], msg)
202
203@script:python depends on org@
204p1 << ss_prev.p1;
205p2 << ss_prev.p2;
206@@
207
208msg = "WARNING: struct_size is already used (line %s) to compute the same size" % (p1[0].line)
209coccilib.org.print_todo(p2[0], msg)
210