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

217 lines
4.4 KiB
Plaintext

// 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
// rest of the file implements the same as 09-merge.cocci
// The main difference is that we only match on snprintf and Debug that are
// directly adjacent, not based on control flow information which trips
// coccinelle's model-checker
@shortcut@
identifier buf;
expression E, L;
expression list args_before, args, args_after;
expression format1, format2;
position p1, p2;
@@
snprintf@p1( buf, E, format1, args );
Debug@p2( L, format2, args_before, buf, args_after );
// use insert_at_pos above to construct the new format-string
@script:python shortcut_process@
format1 << shortcut.format1;
format2 << shortcut.format2;
args_before << shortcut.args_before;
merged;
@@
pos = len(args_before.elements)
coccinelle.merged = insert_at_pos(format2, format1, pos)
@shortcut_replace@
position shortcut.p1, shortcut.p2;
identifier shortcut_process.merged;
identifier buf;
expression E, L;
expression list args_before, args, args_after;
expression format1, format2;
@@
-snprintf@p1( buf, E, format1, args );
-Debug@p2( L, format2, args_before, buf, args_after );
+Debug( L, merged, args_before, args, args_after );
@shortcut_locked@
identifier buf;
expression E, L, lock;
expression list args_before, args, args_after;
expression format1, format2;
position p1, p2;
@@
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 );
// use insert_at_pos above to construct the new format-string
@script:python shortcut_locked_process@
format1 << shortcut_locked.format1;
format2 << shortcut_locked.format2;
args_before << shortcut_locked.args_before;
merged;
@@
pos = len(args_before.elements)
coccinelle.merged = insert_at_pos(format2, format1, pos)
@shortcut_locked_replace@
position shortcut_locked.p1, shortcut_locked.p2;
identifier shortcut_locked_process.merged;
identifier buf;
expression E, L, lock;
expression list args_before, args, args_after;
expression format1, format2;
@@
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 );
// so long as we don't reference 'buf' afterwards, no need to keep it defined.
// A lot of pattern-matching is spelled out explicitly to work around the fact
// that the state space doesn't get compressed otherwise.
@@
type T;
identifier buf, id;
expression E, lock;
initializer I;
@@
{
-\( T buf = I; \| T buf; \)
(
ldap_pvt_thread_mutex_lock(lock);
|
)
(
Debug( ... );
&
... when != buf
)
(
ldap_pvt_thread_mutex_unlock(lock);
|
)
(
|
continue;
|
break;
|
goto id;
|
\(
return E;
\&
... when != buf
\)
)
}
// the rest identifies and removes a (newly-)reduntant LogTest check
@if_guard@
position p;
statement s;
@@
(
if ( ... ) {@p
Debug( ... );
} else s
|
if ( ... ) {@p
Debug( ... );
}
)
@else_guard@
position p;
statement s;
@@
if ( ... ) s
else {@p
Debug( ... );
}
@loop_guard@
position p;
@@
(
while ( ... ) {@p
Debug( ... );
}
|
for ( ...;...;... ) {@p
Debug( ... );
}
)
@@
position p != { if_guard.p , else_guard.p, loop_guard.p };
@@
-{@p
Debug( ... );
-}
@useless_if@
expression L;
@@
-if ( LogTest( L ) ) {
Debug( L, ... );
-}