mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-12 10:54:48 +08:00
217 lines
4.4 KiB
Plaintext
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, ... );
|
|
-}
|