[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