openldap/doc/devel/variadic_debug/09-merge.cocci
2019-02-15 16:51:53 +00:00

148 lines
3.4 KiB
Plaintext

// Note that this file has not actually been used in the end, since
// 07-shortcut.cocci covers everything we needed in the project, but being
// simpler, it makes the intent of 07-shortcut.cocci clearer
// Splice string `s` into the format string `fmtstring` replacing the
// %-parameter at position `pos`
@initialize:python@
@@
#regex from https://stackoverflow.com/questions/30011379/how-can-i-parse-a-c-format-string-in-python
import re
fmtstring = '''\
( # start of capture group 1
% # literal "%"
(?: # first option
(?:[-+0 #]{0,5}) # optional flags
(?:\d+|\*)? # width
(?:\.(?:\d+|\*))? # precision
(?:h|l|ll|w|I|I32|I64)? # size
[cCdiouxXeEfgGaAnpsSZ] # type
) | # OR
%%) # literal "%%"
'''
regex = re.compile(fmtstring, re.X)
def parse_format(f):
return tuple((m.span(), m.group()) for m in
regex.finditer(f))
def insert_at_pos(fmt, s, pos):
formats = parse_format(fmt)
span, format = formats[pos]
acc = fmt[:span[0]]
if s.startswith('"'):
acc += s[1:]
else:
acc += '" '
acc += s
if acc.endswith('"'):
acc = acc[:-1] + fmt[span[1]:]
else:
acc += ' "'
acc += fmt[span[1]:]
return acc
// Identify the redundant snprintfs (within a locked region)
@a exists@
expression lock, E, L;
expression list args_before, args, args_after;
identifier buf;
expression format1, format2;
type T;
position p1, p2;
@@
{
...
T buf;
...
ldap_pvt_thread_mutex_lock(lock);
...
snprintf@p1( buf, E, format1, args );
...
ldap_pvt_thread_mutex_unlock(lock);
...
Debug@p2( L, format2, args_before, buf, args_after );
...
}
// Merge the format strings with insert_at_pos above
@script:python a_process@
format1 << a.format1;
format2 << a.format2;
args_before << a.args_before;
merged;
@@
pos = len(args_before.elements)
coccinelle.merged = insert_at_pos(format2, format1, pos)
// And merge the two together, replacing the extra buffer that's not used anymore
@a_replace@
position a.p1, a.p2;
identifier a_process.merged;
expression lock, E, L;
expression list args_before, args, args_after;
identifier buf;
expression format1, format2;
type T;
@@
{
...
-T buf;
...
ldap_pvt_thread_mutex_lock(lock);
...
-snprintf@p1( buf, E, format1, args );
+Debug( L, merged, args_before, args, args_after );
...
ldap_pvt_thread_mutex_unlock(lock);
...
-Debug@p2( L, format2, args_before, buf, args_after );
...
}
// Once again (same as the 'a' series above, but those that remain to be sorted
// now don't need to stay within a locked region
@b exists@
expression E, L;
expression list args_before, args, args_after;
identifier buf;
expression format1, format2;
position p1, p2;
@@
snprintf@p1( buf, E, format1, args );
...
Debug@p2( L, format2, args_before, buf, args_after );
@script:python b_process@
format1 << b.format1;
format2 << b.format2;
args_before << b.args_before;
merged;
@@
pos = len(args_before.elements)
coccinelle.merged = insert_at_pos(format2, format1, pos)
@b_replace@
position b.p1, b.p2;
identifier b_process.merged;
expression E, L;
expression list args_before, args, args_after;
identifier buf;
expression format1, format2;
@@
-snprintf@p1( buf, E, format1, args );
+Debug( L, merged, args_before, args, args_after );
...
-Debug@p2( L, format2, args_before, buf, args_after );