On Thu, May 18, 2017 at 09:03:31AM +0200, Richard Biener wrote:
> On Wed, May 17, 2017 at 4:10 PM, Marek Polacek <pola...@redhat.com> wrote:
> > We are failing to detect accessing a null pointer in &s->i because
> > v_3 = &s_2->i;
> > is not gimple_assign_load_p:
> > 1997           if (flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT))
> > 1998             {
> > 1999               if (gimple_store_p (stmt))
> > 2000                 instrument_null (gsi, true);
> > 2001               if (gimple_assign_load_p (stmt))
> > 2002                 instrument_null (gsi, false);
> > 2003             }
> >
> > So I think we can use gimple_assign_single_p instead of gimple_assign_load_p
> > and then strip the ADDR_EXPR in instrument_null before getting its base
> > address.  (I've seen stripping ADDR_EXPR before get_base_address elsewhere 
> > in
> > the codebase, too.)
> >
> > Bootstrapped-ubsan/regtested on x86_64-linux, ok for trunk?
> 
> The ADDR_EXPR check covers cases this cannot happen and generally not
> all single rhs are memory or addresses.  But yes, it should work.

Right, I think that's why we check that the result of get_base_address
is a MEM_REF in instrument_null.

> Thus ok.

Thanks.

> Note that we miss to instrument all aggregate arguments to calls and
> asms as well.

:/

> Richard.
> 
> > 2017-05-17  Marek Polacek  <pola...@redhat.com>
> >
> >         PR sanitizer/80797
> >         * ubsan.c (instrument_null): Unwrap ADDR_EXPRs.
> >         (pass_ubsan::execute): Call gimple_assign_single_p instead of
> >         gimple_assign_load_p.
> >
> >         * c-c++-common/ubsan/null-12.c: New test.
> >
> > diff --git gcc/testsuite/c-c++-common/ubsan/null-12.c 
> > gcc/testsuite/c-c++-common/ubsan/null-12.c
> > index e69de29..3478dc1 100644
> > --- gcc/testsuite/c-c++-common/ubsan/null-12.c
> > +++ gcc/testsuite/c-c++-common/ubsan/null-12.c
> > @@ -0,0 +1,42 @@
> > +/* PR sanitizer/80797 */
> > +/* { dg-do run } */
> > +/* { dg-options "-fsanitize=undefined" } */
> > +
> > +struct S
> > +{
> > +  int i;
> > +};
> > +
> > +struct R
> > +{
> > +  struct T {
> > +    int i;
> > +  } *t;
> > +} r;
> > +
> > +int
> > +main ()
> > +{
> > +  struct S *s = 0;
> > +  struct S *s2[1] = { };
> > +
> > +  int *v1 = &s->i;
> > +  int *v2 = &(*s).i;
> > +  int *v3 = &s2[0]->i;
> > +  int *v4 = &s->i + 1;
> > +  int *v5 = &r.t->i;
> > +
> > +  asm ("" : : "r" (&v1) : "memory");
> > +  asm ("" : : "r" (&v2) : "memory");
> > +  asm ("" : : "r" (&v3) : "memory");
> > +  asm ("" : : "r" (&v4) : "memory");
> > +  asm ("" : : "r" (&v5) : "memory");
> > +
> > +  return 0;
> > +}
> > +
> > +/* { dg-output "member access within null pointer of type 'struct 
> > S'\[^\n\r]*(\n|\r\n|\r)" } */
> > +/* { dg-output "\[^\n\r]*member access within null pointer of type 'struct 
> > S'\[^\n\r]*(\n|\r\n|\r)" } */
> > +/* { dg-output "\[^\n\r]*member access within null pointer of type 'struct 
> > S'\[^\n\r]*(\n|\r\n|\r)" } */
> > +/* { dg-output "\[^\n\r]*member access within null pointer of type 'struct 
> > S'\[^\n\r]*(\n|\r\n|\r)" } */
> > +/* { dg-output "\[^\n\r]*member access within null pointer of type 'struct 
> > T'" } */
> > diff --git gcc/ubsan.c gcc/ubsan.c
> > index 4159cc5..a4808d2 100644
> > --- gcc/ubsan.c
> > +++ gcc/ubsan.c
> > @@ -1208,6 +1208,9 @@ instrument_null (gimple_stmt_iterator gsi, bool 
> > is_lhs)
> >  {
> >    gimple *stmt = gsi_stmt (gsi);
> >    tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
> > +  /* Handle also e.g. &s->i.  */
> > +  if (TREE_CODE (t) == ADDR_EXPR)
> > +    t = TREE_OPERAND (t, 0);
> >    tree base = get_base_address (t);
> >    const enum tree_code code = TREE_CODE (base);
> >    if (code == MEM_REF
> > @@ -1998,7 +2001,7 @@ pass_ubsan::execute (function *fun)
> >             {
> >               if (gimple_store_p (stmt))
> >                 instrument_null (gsi, true);
> > -             if (gimple_assign_load_p (stmt))
> > +             if (gimple_assign_single_p (stmt))
> >                 instrument_null (gsi, false);
> >             }

        Marek

Reply via email to