On Wed, Sep 01, 2010 at 09:53:23PM +0200, Julia Lawall wrote:
> > And so if I really had wanted to key off of the initial rcu_read_lock(),
> > I could have done so as follows, correct?
> 
> I'm not sure what the goal of the following is.  Actually, I'm not even 
> sure that regular expressions work for complex expressions like 
> rcu_read_lock(), but even if they do, then in the second rule, rcurscs.r 
> should be a metavariable that matches anything that rcu_read_lock() 
> matches.  So the effect is no different than inlining rcu_read_lock() in 
> the places where you use the r metavariable.
> 
> Maybe, you mean that r should reference a lock call at a specific position 
> in the code.  If that is what you want, then you can use position 
> variables, as in the following simpler examples:
> 
> @@
> position p;
> @@

Got it!

> *...@p();
> ...
> *bar();
> ... when != f...@p();
> *xxx();
> 
> This matches the following code:
> 
> int main () {
>   foo();
>   bar();
>   foo();
>   xxx();
> }
> 
> There is a call to foo between the call to bar and the call to xxx, but 
> that is ok, because it is not at the same position as the initial call to 
> foo.
> 
> On the other hand, the above rule does not match the following code:
> 
> int main () {
>   while (x) {
>     foo();
>     if (a) bar(); else xxx();
>   }
> }
> 
> This time there is a call to foo after the call to bar and before the call 
> to xxx, and this call to foo is that same as the one that was matched 
> before the call to bar.

OK, because we would have to cycle around the loop to match, and the
"when" clause would disqualify the only reasonable match.

Thank you again!

And yet another question...

spatch does not seem to like the following:

        when != if (p) atomic_inc(&<+...p->f1...+>)

The problem I am trying to solve is that it is OK to leak a pointer
out of an RCU read-side critical section if you have done something
to keep the underlying data structure from going away.  One way of
doing this is to increment a reference count in the pointed-to structure,
for example:

        rcu_read_lock();
        p = rcu_dereference(gp);
        if (p && something_bad_happened(p))
                p = NULL
        if (p)
                atomic_inc(&p->refcount);
        rcu_read_unlock();

        if (p)
                do_something_with(p->a);

My current set of rules will flag the last line as a pointer leak,
presumably because there is a code path that skips the atomic_inc().
My first reaction was to just put the "if" statement in a when clause
as above, but that gives a parse error.

I tried a number of variations, including a separate rule matching the
"if" (which worked) and recording the "if"s position (which did not).
For your amusement, one attempt follows.

Thoughts?

                                                        Thanx, Paul

------------------------------------------------------------------------

@guardedref@
position q;
identifier p;
identifier f1;
@@
        if (p...@q) {
                atomic_inc(&p->f1);
        }

@rcupointerleak@
identifier p;
identifier f1, f2, f3;
expression e1, e2, e3;
expression c1;
@@
*       rcu_read_lock();

        ... when any

(
*       p = rcu_dereference(e1);
|
*       p = rcu_dereference_raw(e1);
|
*       p = rcu_dereference_check(e1,c1);
|
*       p = rcu_dereference_index_check(e1,c1);
|
*       list_for_each_entry_rcu(p,e1,f3)
|
*       list_for_each_entry_continue_rcu(p,e1,f3)
|
*       hlist_for_each_entry_rcu(p,e1,f3)
|
*       hlist_for_each_entry_continue_rcu(p,e1,f3)
)

        ... when != p = e2
            when != atomic_inc_not_zero(&<+...p->f1...+>)
            when != atomic_inc_not_zero(&<+...p[e2]...+>)
            when != atomic_inc(&<+...p->f1...+>)
            when != atomic_inc(&<+...p[e2]...+>)
            when != try_module_get(p->owner)
            when != @guardedref.q

*       rcu_read_unlock();

        ... when != p = e2

(
*       *p
|
*       p->f2
|
*       p[e3]
)
_______________________________________________
Cocci mailing list
[email protected]
http://lists.diku.dk/mailman/listinfo/cocci
(Web access from inside DIKUs LAN only)

Reply via email to