Skip to content

Commit 3f1ded6

Browse files
mkindahlCommitfest Bot
authored and
Commitfest Bot
committed
Semantic patch to use stack-allocated StringInfoData
This semantic patch replace uses of StringInfo with StringInfoData where the info is dynamically allocated but (optionally) freed at the end of the block. This will avoid one dynamic allocation that otherwise have to be dealt with. For example, this code: StringInfo info = makeStringInfo(); ... appendStringInfo(info, ...); ... return do_stuff(..., info->data, ...); Can be replaced with: StringInfoData info; initStringInfo(&info); ... appendStringInfo(&info, ...); ... return do_stuff(..., info.data, ...); It does not do a replacement in these cases: - If the variable is assigned to an expression. In this case, the pointer can "leak" outside the function either through a global variable or a parameter assignment. - If an assignment is done to the expression. This cannot leak the data, but could mean a value-assignment of a structure, so we avoid this case. - If the pointer is returned.
1 parent 6a55648 commit 3f1ded6

File tree

1 file changed

+155
-0
lines changed

1 file changed

+155
-0
lines changed

cocci/use_stringinfodata.cocci

+155
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
// Replace uses of StringInfo with StringInfoData where the info is
2+
// dynamically allocated but (optionally) freed at the end of the
3+
// block. This will avoid one dynamic allocation that otherwise have
4+
// to be dealt with.
5+
//
6+
// For example, this code:
7+
//
8+
// StringInfo info = makeStringInfo();
9+
// ...
10+
// appendStringInfo(info, ...);
11+
// ...
12+
// return do_stuff(..., info->data, ...);
13+
//
14+
// Can be replaced with:
15+
//
16+
// StringInfoData info;
17+
// initStringInfo(&info);
18+
// ...
19+
// appendStringInfo(&info, ...);
20+
// ...
21+
// return do_stuff(..., info.data, ...);
22+
23+
virtual report
24+
virtual context
25+
virtual patch
26+
27+
// This rule captures the position of the makeStringInfo() and bases
28+
// all changes around that. It matches the case that we should *not*
29+
// replace, that is, those that either (1) return the pointer or (2)
30+
// assign the pointer to a variable or (3) assign a variable to the
31+
// pointer.
32+
//
33+
// The first two cases are matched because they could potentially leak
34+
// the pointer outside the function, for some expressions, but the
35+
// last one is just a convenience.
36+
//
37+
// If we replace this, the resulting change will result in a value
38+
// copy of a structure, which might not be optimal, so we do not do a
39+
// replacement.
40+
@id1 exists@
41+
typedef StringInfo;
42+
local idexpression StringInfo info;
43+
position pos;
44+
expression E;
45+
@@
46+
info@pos = makeStringInfo()
47+
...
48+
(
49+
return info;
50+
|
51+
info = E
52+
|
53+
E = info
54+
)
55+
56+
@r1 depends on !patch disable decl_init exists@
57+
identifier info, fld;
58+
position dpos, pos != id1.pos;
59+
@@
60+
(
61+
* StringInfo@dpos info;
62+
...
63+
* info@pos = makeStringInfo();
64+
|
65+
* StringInfo@dpos info@pos = makeStringInfo();
66+
)
67+
<...
68+
(
69+
* \(pfree\|destroyStringInfo\)(info);
70+
|
71+
* info->fld
72+
|
73+
* *info
74+
|
75+
* info
76+
)
77+
...>
78+
79+
@script:python depends on report@
80+
info << r1.info;
81+
dpos << r1.dpos;
82+
@@
83+
coccilib.report.print_report(dpos[0], f"Variable '{info}' of type StringInfo can be defined using StringInfoData")
84+
85+
@depends on patch disable decl_init exists@
86+
identifier info, fld;
87+
position pos != id1.pos;
88+
@@
89+
- StringInfo info;
90+
+ StringInfoData info;
91+
...
92+
- info@pos = makeStringInfo();
93+
+ initStringInfo(&info);
94+
<...
95+
(
96+
- \(destroyStringInfo\|pfree\)(info);
97+
|
98+
info
99+
- ->fld
100+
+ .fld
101+
|
102+
- *info
103+
+ info
104+
|
105+
- info
106+
+ &info
107+
)
108+
...>
109+
110+
// Here we repeat the matching of the "bad case" since we cannot
111+
// inherit over modifications
112+
@id2 exists@
113+
typedef StringInfo;
114+
local idexpression StringInfo info;
115+
position pos;
116+
expression E;
117+
@@
118+
info@pos = makeStringInfo()
119+
...
120+
(
121+
return info;
122+
|
123+
info = E
124+
|
125+
E = info
126+
)
127+
128+
@depends on patch exists@
129+
identifier info, fld;
130+
position pos != id2.pos;
131+
statement S, S1;
132+
@@
133+
- StringInfo info@pos = makeStringInfo();
134+
+ StringInfoData info;
135+
... when != S
136+
(
137+
<...
138+
(
139+
- \(destroyStringInfo\|pfree\)(info);
140+
|
141+
info
142+
- ->fld
143+
+ .fld
144+
|
145+
- *info
146+
+ info
147+
|
148+
- info
149+
+ &info
150+
)
151+
...>
152+
&
153+
+ initStringInfo(&info);
154+
S1
155+
)

0 commit comments

Comments
 (0)