[Cocci] Extracting types passed to variadic (varargs) functions
David Malcolm
dmalcolm at redhat.com
Tue Nov 17 20:21:07 CET 2009
On Mon, 2009-11-16 at 23:14 +0100, Julia Lawall wrote:
> On Mon, 16 Nov 2009, 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.
>
> If you really want to analyze all of the arguments at once, I don't see
> how to do it. But perhaps the following would be acceptable (not tested):
>
> @check_PyArg_ParseTuple@
> position pos;
> expression args;
> expresion fmt;
> type t; t e;
> expression list[n] E;
> @@
>
> PyArg_ParseTuple(args at pos, fmt, E, e, ...)
>
> @script:python@
> fmt << check_PyArg_ParseTuple.fmt;
> pos << check_PyArg_ParseTuple.pos;
> t << check_PyArg_ParseTuple.t;
> n << check_PyArg_ParseTuple.n;
> @@
>
> num_errors += validate_types(pos[0], fmt.expr, n, t)
>
> (I'm not sure that the .expr is needed on fmt; or in any case I don't know
> what it does).
>
> Now validate_types takes a position, a format string, the number of
> arguments between the format string and some argument, and that argument.
> The python code will be called on each argument individually.
Thanks. I tried this, but appeared to only match the final argument at
each call site.
However, I reworked it to have an "expression list" both before _and_
after, thus:
@ check_PyArg_ParseTuple @
position pos;
expression args;
expression fmt;
expression list[len_E] E;
expression list[len_F] F;
type t;
t e;
@@
PyArg_ParseTuple at pos(args, fmt, E, e, F)
@script:python@
pos << check_PyArg_ParseTuple.pos;
fmt << check_PyArg_ParseTuple.fmt;
len_E << check_PyArg_ParseTuple.len_E;
len_F << check_PyArg_ParseTuple.len_F;
t << check_PyArg_ParseTuple.t;
@@
num_errors += validate_type(pos[0],
fmt.expr,
int(len_E),
int(len_E) + 1 + int(len_F),
t)
...and it's now successfully matching the rule for each argument, and
supplying the index and the total number of arguments together which
each type, which seems to be everything I needed.
Many thanks!
> > Also, I noticed that positions are passed to Python code as a 1-tuple
> > containing a coccilibs.elems.Location, rather than just the Location
> > itself. Is this deliberate (e.g. to support ranges as well as
> > positions)?
>
> A single position variable can be bound to more than one position when
> using a nest (<... ...> for 0 or more occurrences of the contained pattren
> and <+... ...+> for 1 or more occurrences of the contained pattern). For
> example, if f is a one-argument function, then the following will bind p
> to each occurrence of e in that argument:
>
> f(<+...e at p...+>)
>
> Then you can use for to iterate over them.
Thanks for the clarification.
More information about the Cocci
mailing list