[Cocci] Extracting types passed to variadic (varargs) functions

Julia Lawall julia at diku.dk
Tue Nov 17 21:23:58 CET 2009


On Tue, 17 Nov 2009, David Malcolm wrote:

> On Mon, 2009-11-16 at 23:12 +0100, Nicolas Palix wrote: 
> > On Monday 16 November 2009 22:41:40 David Malcolm wrote:
> > > I'm new to Coccinelle/spatch and have been experimenting with using it
> > > upon CPython code [1]
> > > 
> > > I'm attempting to validate a mini-language used in format strings by a
> > > variadic API call.  My code examines the types of the
> > > variables passed as varargs, and attempts to check that they are
> > > pointers of the correct types, according to a set of rules [2].
> > > 
> > > Unfortunately, I couldn't see a way to match a variable-length list of
> > > expressions, capturing the type of each expression.
> > > 
> > > So my current code adopts the ugly approach of manually writing a rule
> > > for each number of arguments, so I have a rule :
> > > @ check_PyArg_ParseTuple_1 @
> > > another named:
> > > @ check_PyArg_ParseTuple_2 @
> > > and so on.
> > > 
> > > Is there a better way of doing this in Coccinelle?  How can I match a
> > > variable number of comma-separated expressions, passing the types of all
> > > of the expressions to a python script?
> > 
> > You can use "expression list". Here is an example:
> > http://cocci.ekstranet.diku.dk/wiki/doku.php?id=add_a_parameter_throughout_a_call_chain
> 
> Thanks!
> 
> I tried the following:
> @ check_PyArg_ParseTuple @
> position pos;
> expression args;
> expression fmt;
> expression list ES;
> @@
> 
> PyArg_ParseTuple at pos(args, fmt, ES)
> 
> @script:python@
> pos << check_PyArg_ParseTuple_1.pos;
> fmt << check_PyArg_ParseTuple_1.fmt;
> es << check_PyArg_ParseTuple_1.ES;
> @@
> print es
> print type(es)
> 
> ...but all I get is a "TODO: <<exprlist>>" string (this is with
> coccinelle-0.1.10).

Expression lists are indeed a bit undersupported.  This case should be 
easy to fix, though.

> I then tried generating a rule of the correct length:
> 
> @ gen_PyArg_ParseTuple @
> position pos;
> expression args;
> expression fmt;
> expression list ES;
> @@
> 
> PyArg_ParseTuple at pos(args, fmt, ES)
> 
> @script:python@
> pos <<gen_PyArg_ParseTuple.pos;
> es << gen_PyArg_ParseTuple.ES;
> @@
> print pos[0].__dict__
> rulename = 'check_PyArg_ParseTuple_%i' % len(es)
> metavars = '''position pos;
> expression args;
> expression fmt;
> '''
> for i in range(len(es)):
>     metavars += 'type t%d; t%i e%i;\n' % (i, i, i)
> exprlist = ','.join(['e%i'%i for i in range(len(es))])
> capturedvars = '\n'.join(['t%i << %s.%i'%(i,rulename,i) for i in
> range(len(es))])
> typelist = ','.join(['t%i'%i for i in range(len(es))])
> print """
> @ %(rulename)s @
> %(metavars)s
> @@
> 
> PyArg_ParseTuple(args at pos, fmt, %(exprlist)s)
> 
> @script:python@
> fmt << %(rulename)s.fmt;
> pos << %(rulename)s.pos;
> %(capturedvars)s
> @@
> num_errors += validate_types(pos[0], fmt.expr, [%(typelist)s])
> """ % locals()
> 
> 
> which prints a cocci rule to stdout.
> 
> For some reason, the expression list has a length of 18 (not sure why)
> 
> Is there an automatic way to have spatch recursively execute the rule,
> rather than just print it to stdout?  (in the example you gave, were you
> capturing the result then rerunning spatch upon it?)

No, at the moment there is nothing to support this, although it could be a 
useful feature.

julia


More information about the Cocci mailing list