How about trying:

@@
identifier n;
expression E;
@@

... when != n = E
cartoon_random_generator(&n)

Since your code uses inout parameters, you might want to have a second 
"when" line with when != &n

I'll take a look at why your proposition doesn't work shortly.  Overall, 
it seems a bit overspecified, though.

julia

On Fri, 7 Oct 2011, Håkon Løvdal wrote:

> I have a question/problem where I want to detect sending the address
> of an uninitialized
> variable into a function. The details are described at
> http://stackoverflow.com/questions/7685898/detect-passing-pointer-to-uninitialized-variable.
> 
> I know that there is more expertise about coccinelle here on the
> mailing list than on stackoverflow,
> but the question is so general that when answered it will be of
> benefit for many more people when
> present there. Feel free to just answer here on the mailing list, I
> can update stackoverflow as appropriate.
> 
> BR Håkon Løvdal
> 
> A copy of the question is as follows:
> 
> Some functions have a pointer argument that points to where a result
> from calling the function should be stored, but the function also
> require that when calling the function this pointer points to some
> value used as input value (e.g. an in/out parameter).
> 
> I want to detect cases where such functions are called pointing to
> uninitialized variables. Coccinelle should be able to do this, however
> I struggle a little to achieve this.
> 
> Example target code:
> 
> #include <string.h>
> #include <stdio.h>
> 
> static void cartoon_random_generator(int *n)
> {
>     switch (*n) {
>     case 4:
>         *n = 4; /* http://xkcd.com/221/ */
>         break;
>     case 9:
>         *n = 9; /* http://dilbert.com/strips/comic/2001-10-25/ */
>         break;
>     default:
>         fprintf(stderr, "*n was not initialized before calling this
> function\n");
>         break;
>     }
> }
> /* alternative links http://i.stack.imgur.com/VvTef.png and
> http://i.stack.imgur.com/u0iJ7.gif */
> 
> static void test(const char *cartoon)
> {
>     // not ok, missing
>     {
>         int n1;
> 
>         cartoon_random_generator(&n1);
>         printf("Random number = %d\n", n1);
>     }
> 
>     // ok, declaration
>     {
>         int n2 = 4;
> 
>         cartoon_random_generator(&n2);
>         printf("Random number = %d\n", n2);
>     }
> 
>     // ok, statement
>     {
>         int n3;
> 
>         n3 = 9;
>         cartoon_random_generator(&n3);
>         printf("Random number = %d\n", n3);
>     }
> 
>     // both ok and not ok
>     {
>         int n4, n9;
> 
>         n9 = 9;
>         //strcmp(cartoon, "XKCD") == 0 ? cartoon_random_generator(&n4)
> : cartoon_random_generator(&n9);
>         if (strcmp(cartoon, "XKCD") == 0)
>             cartoon_random_generator(&n4);
>         else
>             cartoon_random_generator(&n9);
>         printf("Random numbers = %d, %d\n", n4, n9);
>     }
> }
> 
> I have written the following coccinelle script
> 
> /* It is an error to call cartoon_random_generator with an uninitialized
>    variable. Detect this. */
> 
> 
> /*
>  * This rule matches an OK case where the in variable is initialized when
>  * declared. No action is performed for this rule other than giving p1 a 
> value.
>  */
> @rule1@
> position p1;
> expression init_expression;
> identifier n;
> @@
> 
> int n = init_expression;
> ...
> cartoon_random_generator@p1(&n)
> 
> 
> /*
>  * This rule matches an OK case where the in variable is initialized in a
>  * separate statement. No action is performed for this rule other than
>  * giving p2 a value.
>  */
> @rule2@
> position p2;
> expression init_expression;
> identifier n;
> @@
> 
> int n;
> ...
> n = init_expression;
> ...
> cartoon_random_generator@p2(&n)
> 
> 
> /* If neither rule1 or rule2 have matched so far,
>  * we have a variable that is uninitialized. */
> 
> @rule3@
> position p3 != rule1.p1, rule2.p2;
> identifier n;
> @@
> 
> int n;
> ...
> * cartoon_random_generator@p3(&n)
> 
> but rule2 is not taken into account and I do not understand why.
> Running it gives:
> 
> $ /opt/coccinelle/bin/spatch -sp_file cartoon_random.cocci cartoon_random.c
> init_defs_builtins: /opt/coccinelle/share/coccinelle/standard.h
> warning: rule3: inherited metavariable p2 not used in the -, +, or context 
> code
> HANDLING: cartoon_random.c
> diff =
> --- cartoon_random.c
> +++ /tmp/cocci-output-7916-8df75b-cartoon_random.c
> @@ -23,7 +23,6 @@ static void test(const char *cartoon)
>         {
>                 int n1;
> 
> -               cartoon_random_generator(&n1);
>                 printf("Random number = %d\n", n1);
>         }
> 
> @@ -40,7 +39,6 @@ static void test(const char *cartoon)
>                 int n3;
> 
>                 n3 = 9;
> -               cartoon_random_generator(&n3);
>                 printf("Random number = %d\n", n3);
>         }
> 
> @@ -51,9 +49,7 @@ static void test(const char *cartoon)
>                 n9 = 9;
>                 //strcmp(cartoon, "XKCD") == 0 ?
> cartoon_random_generator(&n4) : cartoon_random_generator(&n9);
>                 if (strcmp(cartoon, "XKCD") == 0)
> -                       cartoon_random_generator(&n4);
>                 else
> -                       cartoon_random_generator(&n9);
>                 printf("Random numbers = %d, %d\n", n4, n9);
>         }
>  }
> _______________________________________________
> Cocci mailing list
> [email protected]
> http://lists.diku.dk/mailman/listinfo/cocci
> (Web access from inside DIKUs LAN only)
> 
_______________________________________________
Cocci mailing list
[email protected]
http://lists.diku.dk/mailman/listinfo/cocci
(Web access from inside DIKUs LAN only)

Reply via email to