On 09/17/18 20:32, Jeff Law wrote:
> On 9/17/18 12:20 PM, Bernd Edlinger wrote:
>> On 09/17/18 19:33, Jeff Law wrote:
>>> On 9/16/18 1:58 PM, Bernd Edlinger wrote:
>>>> Hi,
>>>>
>>>> this is a cleanup of the recently added strlen/strcpy/stpcpy
>>>> no nul warning code.
>>>>
>>>> Most importantly it moves the SSA_NAME handling from
>>>> unterminated_array to string_constant, thereby fixing
>>>> another round of xfails in the strlen and stpcpy test cases.
>>>>
>>>> I need to say that the fix for bug 86622 is relying in
>>>> type info on the pointer which is probably not safe in
>>>> GIMPLE in the light of the recent discussion.
>>>>
>>>> I had to add two further exceptions, which should
>>>> be safe in general: that is a pointer arithmentic on a string
>>>> literal is okay, and arithmetic on a string constant
>>>> that is exactly the size of the whole DECL, cannot
>>>> access an adjacent member.
>>>>
>>>>
>>>> Bootstrapped and reg-tested on x86_64-pc-linux-gnu.
>>>> Is it OK for trunk?
>>>>
>>>>
>>>> Thanks
>>>> Bernd.
>>>>
>>>>
>>>> patch-cleanup-no-nul.diff
>>>>
>>>> gcc:
>>>> 2018-09-16  Bernd Edlinger  <bernd.edlin...@hotmail.de>
>>>>
>>>>    * builtins.h (unterminated_array): Remove prototype.
>>>>           * builtins.c (unterminated_array): Simplify.  Make static.
>>>>           (expand_builtin_strcpy_args): Don't use TREE_NO_WARNING here.
>>>>    (expand_builtin_stpcpy_1): Remove warn_string_no_nul without effect.
>>>>    * expr.c (string_constant): Handle SSA_NAME.  Add more exceptions
>>>>    where pointer arithmetic is safe.
>>>>    * gimple-fold.c (get_range_strlen): Handle nonstr like in c_strlen.
>>>>    (get_max_strlen): Remove the unnecessary mynonstr handling.
>>>>    (gimple_fold_builtin_strcpy): Simplify.
>>>>    (gimple_fold_builtin_stpcpy): Simplify.
>>>>    (gimple_fold_builtin_sprintf): Remove NO_WARNING propagation
>>>>    without effect.
>>>>    (gimple_fold_builtin_strlen): Simplify.
>>>>
>>>> testsuite:
>>>> 2018-09-16  Bernd Edlinger  <bernd.edlin...@hotmail.de>
>>>>
>>>>    * gcc.dg/warn-stpcpy-no-nul.c: Remove xfails.
>>>>    * gcc.dg/warn-strlen-no-nul.c: Remove xfails.
>>>>
>>>> Index: gcc/builtins.c
>>>> ===================================================================
>>>> --- gcc/builtins.c (revision 264342)
>>>> +++ gcc/builtins.c (working copy)
>>>> @@ -567,31 +567,12 @@ warn_string_no_nul (location_t loc, const char *fn
>>>>       the declaration of the object of which the array is a member or
>>>>       element.  Otherwise return null.  */
>>>>    
>>>> -tree
>>>> +static tree
>>>>    unterminated_array (tree exp)
>>>>    {
>>>> -  if (TREE_CODE (exp) == SSA_NAME)
>>>> -    {
>>>> -      gimple *stmt = SSA_NAME_DEF_STMT (exp);
>>>> -      if (!is_gimple_assign (stmt))
>>>> -  return NULL_TREE;
>>>> -
>>>> -      tree rhs1 = gimple_assign_rhs1 (stmt);
>>>> -      tree_code code = gimple_assign_rhs_code (stmt);
>>>> -      if (code == ADDR_EXPR
>>>> -    && TREE_CODE (TREE_OPERAND (rhs1, 0)) == ARRAY_REF)
>>>> -  rhs1 = rhs1;
>>>> -      else if (code != POINTER_PLUS_EXPR)
>>>> -  return NULL_TREE;
>>>> -
>>>> -      exp = rhs1;
>>>> -    }
>>>> -
>>>>      tree nonstr = NULL;
>>>> -  if (c_strlen (exp, 1, &nonstr, 1) == NULL && nonstr)
>>>> -    return nonstr;
>>>> -
>>>> -  return NULL_TREE;
>>>> +  c_strlen (exp, 1, &nonstr);
>>>> +  return nonstr;
>>>>    }
>>> Sigh.  This is going to conflict with patch #6 from Martin's kit.
>>>
>>
>> Sorry, it just feels wrong to do this folding here instead of in
>> string_constant.
>>
>> I think the handling of POINTER_PLUS_EXPR above, is faulty,
>> because it is ignoring the offset parameter, which typically
>> contains the offset part, may add an offset to a different
>> structure member or another array index.  That is what happened
>> in PR 86622.
>>
>> So you are likely looking at the wrong index, or even the wrong
>> structure member.
> I'm not disagreeing that something's wrong here -- the whole concept
> that we extract the rhs and totally ignore the offset seems wrong.  I've
> stumbled over it working through issues with either patch #4 or #6 from
> Martin.  But I felt I needed to go back and reevaluate any assumptions I
> had about how the code was supposed to be used before I called it out.
> 
> 
> Your expr.c changes may be worth pushing through independently of the
> rest.    AFAICT they're really just exposing more cases where we can
> determine that we're working with a stirng constant.
> 

I think that moves just the folding from here to expr.c,
I don't see how the change in part #6 on unterminated_array
is supposed to work, I quote it here and add some comments:

>  tree
> -unterminated_array (tree exp)
> +unterminated_array (tree exp, tree *size /* = NULL */, bool *exact /* = NULL 
> */)
>  {
> +  /* Offset from the beginning of the array or null.  */
> +  tree off = NULL_TREE;
> +
>    if (TREE_CODE (exp) == SSA_NAME)
>      {
>        gimple *stmt = SSA_NAME_DEF_STMT (exp);
> @@ -595,18 +600,43 @@ unterminated_array (tree exp)
>  
>        tree rhs1 = gimple_assign_rhs1 (stmt);
>        tree_code code = gimple_assign_rhs_code (stmt);
> -      if (code == ADDR_EXPR
> -       && TREE_CODE (TREE_OPERAND (rhs1, 0)) == ARRAY_REF)
> -     rhs1 = rhs1;
> -      else if (code != POINTER_PLUS_EXPR)
> +      if ((code == ADDR_EXPR
> +        && TREE_CODE (TREE_OPERAND (rhs1, 0)) == ARRAY_REF)
> +       || code == POINTER_PLUS_EXPR)
> +     {
> +       /* Store the index or offset.  */
> +       off = gimple_assign_rhs2 (stmt);

ADDR_EXPR does not have rhs2, right?

> +       exp = rhs1;
> +     }
> +      else
>       return NULL_TREE;
> -
> -      exp = rhs1;
>      }
>  
>    tree nonstr;
> -  if (c_strlen (exp, 1, &nonstr) && nonstr)
> -    return nonstr;
> +  tree len = c_strlen (exp, 1, &nonstr);
> +  if (len && nonstr)
> +    {
> +      if (size)
> +     {
> +       if (off)
> +         {
> +           if (TREE_CODE (off) == INTEGER_CST)
> +             {
> +               /* Subtract the offset from the size of the array.  */
> +               *exact = true;
> +               off = fold_convert (ssizetype, off);
> +               len = fold_build2 (MINUS_EXPR, ssizetype, len, off);

Underflow could happen here, off could even be negative.

Something similar to the check in string_constant should be done to avoid
that off might be moving the access to another array member:

           if (POINTER_TYPE_P (TREE_TYPE (rhs1))
               && TREE_CODE (TREE_TYPE (TREE_TYPE (rhs1))) == ARRAY_TYPE
               && !(decl && !*decl)
               && !(decl && tree_fits_uhwi_p (DECL_SIZE_UNIT (*decl))
                    && mem_size && tree_fits_uhwi_p (*mem_size)
                    && tree_int_cst_equal (*mem_size, DECL_SIZE_UNIT (*decl))))


> +             }
> +           else
> +             *exact = false;
> +         }
> +       else
> +         *exact = true;
> +
> +       *size = len;
> +     }
> +      return nonstr;
> +    }
>  
>    return NULL_TREE;
>  }

Yeah, sorry, but this looks like a hack.

I would just use c_strlen if I need the length
and optionally nonstr.

The previous version was a convenience when you
are only interested in nonstr, which may happen.

I suppose the expr.c change will likely work alone, but
it was designed to replace the stuff here.

So I will try to split the expr.c part out, and post it
tomorrow.


Bernd.

Reply via email to