public inbox for smatch@vger.kernel.org
 help / color / mirror / Atom feed
* noreturn attribute doesn't work in smatch
@ 2019-08-15  0:53 John Levon
  2019-08-15 11:12 ` John Levon
  0 siblings, 1 reply; 6+ messages in thread
From: John Levon @ 2019-08-15  0:53 UTC (permalink / raw)
  To: smatch, linux-sparse; +Cc: yuri.pankov


./smatch: a.c:20 main() error: double free of 'str'

given:

```
#include <stdlib.h>
#include <string.h>

__attribute__((__noreturn__)) void
die(void)
{
        exit(1);
}

int
main(void)
{
        char *str = strdup("test");

        if (str != NULL) {
                free(str);
                die();
        }

        free(str);

        return (0);
}
```

As far as I can figure out, this looks like a sparse problem: an
'inline' or 'extern' specifier in this position gets marked as the
relevant MOD_* flag for the function, but the noreturn doesn't bubble
up in the same way. Some quick lame attempts to add ctx->is_noreturn did
not go well.

I think this might be the underlying issue behind sparse's failing test
validation/function-redecl2.c but I'm not positive.

We can do:

```
#ifdef __CHECKER__
#define SMATCH_NORETURN __attribute__((__noreturn__))
#else
#define SMATCH_NORETURN /* would break gcc otherwise */
#endif

__attribute__((__noreturn__)) void
die(void) SMATCH_NORETURN
{
```

but it's ... unlovely.

Any thoughts?

thanks
john

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: noreturn attribute doesn't work in smatch
  2019-08-15  0:53 noreturn attribute doesn't work in smatch John Levon
@ 2019-08-15 11:12 ` John Levon
  2019-08-22 13:30   ` Dan Carpenter
  0 siblings, 1 reply; 6+ messages in thread
From: John Levon @ 2019-08-15 11:12 UTC (permalink / raw)
  To: smatch, linux-sparse; +Cc: yuri.pankov


I took another pass, and this works for me:

diff --git a/parse.c b/parse.c
index ca4726b8..44c59707 100644
--- a/parse.c
+++ b/parse.c
@@ -2859,6 +2859,7 @@ struct token *external_declaration(struct token
*token, struct symbol_list **lis
        /* Parse declaration-specifiers, if any */
        token = declaration_specifiers(token, &ctx);
        mod = storage_modifiers(&ctx);
+       mod |= ctx.ctype.modifiers & MOD_NORETURN;
        decl = alloc_symbol(token->pos, SYM_NODE);
        /* Just a type declaration? */
        if (match_op(token, ';')) {

(I suppose a proper fix would collate all function-level attributes
but...)


However, it seems like smatch is still not quite passing its knowledge
along: if I have:

extern void die() __attribute((__noreturn__));

void mydie()
{
	die();
}

then the die() call is nullified, but smatch doesn't realise that means
all paths of mydie() are __noreturn__ too.

regards
john

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: noreturn attribute doesn't work in smatch
  2019-08-15 11:12 ` John Levon
@ 2019-08-22 13:30   ` Dan Carpenter
  2019-08-22 13:46     ` John Levon
  0 siblings, 1 reply; 6+ messages in thread
From: Dan Carpenter @ 2019-08-22 13:30 UTC (permalink / raw)
  To: John Levon; +Cc: smatch, linux-sparse, yuri.pankov

On Thu, Aug 15, 2019 at 12:12:37PM +0100, John Levon wrote:
> 
> I took another pass, and this works for me:
> 
> diff --git a/parse.c b/parse.c
> index ca4726b8..44c59707 100644
> --- a/parse.c
> +++ b/parse.c
> @@ -2859,6 +2859,7 @@ struct token *external_declaration(struct token
> *token, struct symbol_list **lis
>         /* Parse declaration-specifiers, if any */
>         token = declaration_specifiers(token, &ctx);
>         mod = storage_modifiers(&ctx);
> +       mod |= ctx.ctype.modifiers & MOD_NORETURN;
>         decl = alloc_symbol(token->pos, SYM_NODE);
>         /* Just a type declaration? */
>         if (match_op(token, ';')) {
> 
> (I suppose a proper fix would collate all function-level attributes
> but...)
> 

This patch seems like a hack, but I will apply it...

> 
> However, it seems like smatch is still not quite passing its knowledge
> along: if I have:
> 
> extern void die() __attribute((__noreturn__));
> 
> void mydie()
> {
> 	die();
> }
> 
> then the die() call is nullified, but smatch doesn't realise that means
> all paths of mydie() are __noreturn__ too.

The code to handle that is really ancient.  You need to do:
    ./smatch --info test.c | tee warns.txt
    grep no_return_funcs warns.txt || echo FAIL
    ./smatch_scripts/gen_no_return_funcs.sh warns.txt -p=levon
    mv levon.no_return_funcs smatch_data/

Then pass -p=levon to smatch on the next run.

regards,
dan carpenter

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: noreturn attribute doesn't work in smatch
  2019-08-22 13:30   ` Dan Carpenter
@ 2019-08-22 13:46     ` John Levon
  2019-08-22 15:05       ` Dan Carpenter
  0 siblings, 1 reply; 6+ messages in thread
From: John Levon @ 2019-08-22 13:46 UTC (permalink / raw)
  To: Dan Carpenter; +Cc: smatch, linux-sparse, yuri.pankov

On Thu, Aug 22, 2019 at 04:30:34PM +0300, Dan Carpenter wrote:

> On Thu, Aug 15, 2019 at 12:12:37PM +0100, John Levon wrote:
> > 
> > I took another pass, and this works for me:
> > 
> > diff --git a/parse.c b/parse.c
> > index ca4726b8..44c59707 100644
> > --- a/parse.c
> > +++ b/parse.c
> > @@ -2859,6 +2859,7 @@ struct token *external_declaration(struct token
> > *token, struct symbol_list **lis
> >         /* Parse declaration-specifiers, if any */
> >         token = declaration_specifiers(token, &ctx);
> >         mod = storage_modifiers(&ctx);
> > +       mod |= ctx.ctype.modifiers & MOD_NORETURN;
> >         decl = alloc_symbol(token->pos, SYM_NODE);
> >         /* Just a type declaration? */
> >         if (match_op(token, ';')) {
> > 
> > (I suppose a proper fix would collate all function-level attributes
> > but...)
> 
> This patch seems like a hack, but I will apply it...

I agree, it would be nice to see this cleaned up properly, but as the
above is sufficient for us, it'll do for us! Thanks!

> > However, it seems like smatch is still not quite passing its knowledge
> > along: if I have:
> > 
> > extern void die() __attribute((__noreturn__));
> > 
> > void mydie()
> > {
> > 	die();
> > }
> > 
> > then the die() call is nullified, but smatch doesn't realise that means
> > all paths of mydie() are __noreturn__ too.
> 
> The code to handle that is really ancient.  You need to do:
>     ./smatch --info test.c | tee warns.txt
>     grep no_return_funcs warns.txt || echo FAIL
>     ./smatch_scripts/gen_no_return_funcs.sh warns.txt -p=levon
>     mv levon.no_return_funcs smatch_data/
> 
> Then pass -p=levon to smatch on the next run.

OK, thanks. That doesn't match too well with the way we use smatch, but
this is much less of a big deal (I only needed to annotate this in a
couple of places).

regards
john

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: noreturn attribute doesn't work in smatch
  2019-08-22 13:46     ` John Levon
@ 2019-08-22 15:05       ` Dan Carpenter
  2019-08-22 15:29         ` John Levon
  0 siblings, 1 reply; 6+ messages in thread
From: Dan Carpenter @ 2019-08-22 15:05 UTC (permalink / raw)
  To: John Levon; +Cc: smatch, linux-sparse, yuri.pankov

On Thu, Aug 22, 2019 at 02:46:03PM +0100, John Levon wrote:
> On Thu, Aug 22, 2019 at 04:30:34PM +0300, Dan Carpenter wrote:
> > The code to handle that is really ancient.  You need to do:
> >     ./smatch --info test.c | tee warns.txt
> >     grep no_return_funcs warns.txt || echo FAIL
> >     ./smatch_scripts/gen_no_return_funcs.sh warns.txt -p=levon
> >     mv levon.no_return_funcs smatch_data/
> > 
> > Then pass -p=levon to smatch on the next run.
> 
> OK, thanks. That doesn't match too well with the way we use smatch, but
> this is much less of a big deal (I only needed to annotate this in a
> couple of places).

It should be the the DB, right?  Would that work for you?

It's sort of an awkward thing because I publish the list of no return
functions used in the kernel, but I don't publish the DB.  So I probably
have to keep both methods...

regards,
dan carpenter

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: noreturn attribute doesn't work in smatch
  2019-08-22 15:05       ` Dan Carpenter
@ 2019-08-22 15:29         ` John Levon
  0 siblings, 0 replies; 6+ messages in thread
From: John Levon @ 2019-08-22 15:29 UTC (permalink / raw)
  To: Dan Carpenter; +Cc: smatch, linux-sparse, yuri.pankov

On Thu, Aug 22, 2019 at 06:05:29PM +0300, Dan Carpenter wrote:

> On Thu, Aug 22, 2019 at 02:46:03PM +0100, John Levon wrote:
> > On Thu, Aug 22, 2019 at 04:30:34PM +0300, Dan Carpenter wrote:
> > > The code to handle that is really ancient.  You need to do:
> > >     ./smatch --info test.c | tee warns.txt
> > >     grep no_return_funcs warns.txt || echo FAIL
> > >     ./smatch_scripts/gen_no_return_funcs.sh warns.txt -p=levon
> > >     mv levon.no_return_funcs smatch_data/
> > > 
> > > Then pass -p=levon to smatch on the next run.
> > 
> > OK, thanks. That doesn't match too well with the way we use smatch, but
> > this is much less of a big deal (I only needed to annotate this in a
> > couple of places).
> 
> It should be the the DB, right?  Would that work for you?

There's few enough that it's preferable to just explicitly mark the
source as noreturn too, rather than keep a separate list.

regards
john

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2019-08-22 15:29 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-08-15  0:53 noreturn attribute doesn't work in smatch John Levon
2019-08-15 11:12 ` John Levon
2019-08-22 13:30   ` Dan Carpenter
2019-08-22 13:46     ` John Levon
2019-08-22 15:05       ` Dan Carpenter
2019-08-22 15:29         ` John Levon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox