Skip to content

Commit dcbf70f

Browse files
authored
Merge pull request #1279 from geoffw0/large-parameter
CPP: Tests and changes for LargeParameter.ql
2 parents 490dd0e + a5b9df2 commit dcbf70f

File tree

3 files changed

+135
-1
lines changed

3 files changed

+135
-1
lines changed

cpp/ql/src/Critical/LargeParameter.ql

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
*/
1313

1414
import cpp
15+
import semmle.code.cpp.dataflow.EscapesTree
1516

1617
from Function f, Parameter p, Type t, int size
1718
where
@@ -20,7 +21,21 @@ where
2021
t.getSize() = size and
2122
size > 64 and
2223
not t.getUnderlyingType() instanceof ArrayType and
23-
not f instanceof CopyAssignmentOperator
24+
not f instanceof CopyAssignmentOperator and
25+
// exception: p is written to, which may mean the copy is intended
26+
not p.getAnAccess().isAddressOfAccessNonConst() and
27+
not exists(Expr e |
28+
variableAccessedAsValue(p.getAnAccess(), e.getFullyConverted()) and
29+
(
30+
exists(Assignment an | an.getLValue() = e)
31+
or
32+
exists(CrementOperation co | co.getOperand() = e)
33+
or
34+
exists(FunctionCall fc | fc.getQualifier() = e and not fc.getTarget().hasSpecifier("const"))
35+
)
36+
) and
37+
// if there's no block, we can't tell how the parameter is used
38+
exists(f.getBlock())
2439
select p,
2540
"This parameter of type $@ is " + size.toString() +
2641
" bytes - consider passing a const pointer/reference instead.", t, t.toString()
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
11
| test.cpp:16:13:16:14 | _t | This parameter of type $@ is 4096 bytes - consider passing a const pointer/reference instead. | test.cpp:6:8:6:20 | myLargeStruct | myLargeStruct |
22
| test.cpp:24:44:24:48 | mtc_t | This parameter of type $@ is 4096 bytes - consider passing a const pointer/reference instead. | test.cpp:11:7:11:21 | myTemplateClass<myLargeStruct> | myTemplateClass<myLargeStruct> |
33
| test.cpp:28:49:28:49 | b | This parameter of type $@ is 4096 bytes - consider passing a const pointer/reference instead. | test.cpp:6:8:6:20 | myLargeStruct | myLargeStruct |
4+
| test.cpp:104:16:104:16 | a | This parameter of type $@ is 4100 bytes - consider passing a const pointer/reference instead. | test.cpp:58:8:58:19 | MyLargeClass | MyLargeClass |
5+
| test.cpp:105:16:105:16 | b | This parameter of type $@ is 4100 bytes - consider passing a const pointer/reference instead. | test.cpp:58:8:58:19 | MyLargeClass | MyLargeClass |
6+
| test.cpp:106:16:106:16 | c | This parameter of type $@ is 4100 bytes - consider passing a const pointer/reference instead. | test.cpp:58:8:58:19 | MyLargeClass | MyLargeClass |
7+
| test.cpp:107:16:107:16 | d | This parameter of type $@ is 4100 bytes - consider passing a const pointer/reference instead. | test.cpp:58:8:58:19 | MyLargeClass | MyLargeClass |
8+
| test.cpp:108:16:108:16 | e | This parameter of type $@ is 4100 bytes - consider passing a const pointer/reference instead. | test.cpp:58:8:58:19 | MyLargeClass | MyLargeClass |
9+
| test.cpp:109:16:109:16 | f | This parameter of type $@ is 4100 bytes - consider passing a const pointer/reference instead. | test.cpp:58:8:58:19 | MyLargeClass | MyLargeClass |
10+
| test.cpp:161:7:161:7 | b | This parameter of type $@ is 3208 bytes - consider passing a const pointer/reference instead. | test.cpp:153:8:153:10 | big | big |

cpp/ql/test/query-tests/Critical/LargeParameter/test.cpp

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,115 @@ struct CustomAssignmentOp {
5252
CustomAssignmentOp &operator=(CustomAssignmentOp rhs);
5353
char data[4096];
5454
};
55+
56+
// ---
57+
58+
struct MyLargeClass {
59+
public:
60+
MyLargeClass();
61+
62+
void myMethod();
63+
void myConstMethod() const;
64+
65+
int value;
66+
char data[4096];
67+
};
68+
69+
void mlc_modify(MyLargeClass &c) {
70+
c.value++;
71+
}
72+
73+
int mlc_get(const MyLargeClass &c) {
74+
return c.value;
75+
}
76+
77+
void myFunction4(
78+
MyLargeClass a, // GOOD: large, but the copy is written to so can't be trivially replaced with a reference
79+
MyLargeClass b, // GOOD
80+
MyLargeClass c, // GOOD
81+
MyLargeClass d, // GOOD
82+
MyLargeClass e, // GOOD
83+
MyLargeClass f, // GOOD
84+
MyLargeClass g // GOOD
85+
)
86+
{
87+
MyLargeClass *mlc_ptr;
88+
int *i_ptr;
89+
90+
a.value++;
91+
b.value = 1;
92+
c.data[0] += 1;
93+
d.myMethod();
94+
mlc_modify(e);
95+
96+
mlc_ptr = &f;
97+
mlc_modify(*mlc_ptr);
98+
99+
i_ptr = &g.value;
100+
*(i_ptr)++;
101+
}
102+
103+
void myFunction5(
104+
MyLargeClass a, // BAD
105+
MyLargeClass b, // BAD
106+
MyLargeClass c, // BAD
107+
MyLargeClass d, // BAD
108+
MyLargeClass e, // BAD
109+
MyLargeClass f // BAD
110+
)
111+
{
112+
const MyLargeClass *mlc_ptr;
113+
const int *i_ptr;
114+
int i;
115+
116+
i = a.value;
117+
i += b.data[0];
118+
c.myConstMethod();
119+
i += mlc_get(d);
120+
121+
mlc_ptr = &e;
122+
mlc_get(*mlc_ptr);
123+
124+
i_ptr = &f.value;
125+
i += *i_ptr;
126+
}
127+
128+
// ---
129+
130+
class MyArithmeticClass {
131+
public:
132+
MyArithmeticClass(int _value) : value(_value) {};
133+
134+
MyArithmeticClass &operator+=(const MyArithmeticClass &other) {
135+
this->value += other.value;
136+
return *this;
137+
}
138+
139+
private:
140+
int value;
141+
char data[1024];
142+
};
143+
144+
MyArithmeticClass operator+(MyArithmeticClass lhs, const MyArithmeticClass &rhs) { // GOOD
145+
lhs += rhs; // lhs is copied by design
146+
return lhs;
147+
}
148+
149+
void myFunction6(MyLargeClass a); // GOOD (no definition, so we can't tell what's done with `a`)
150+
151+
// ---
152+
153+
struct big
154+
{
155+
int xs[800];
156+
int *ptr;
157+
};
158+
159+
void myFunction7(
160+
big a, // GOOD
161+
big b // BAD
162+
)
163+
{
164+
a.xs[0]++; // modifies a
165+
b.ptr[0]++; // does not modify b
166+
}

0 commit comments

Comments
 (0)