On Fri, Jun 9, 2017 at 2:08 PM, Martin Liška <mli...@suse.cz> wrote:
> On 06/09/2017 01:05 PM, Richard Biener wrote:
>>
>> On Fri, Jun 9, 2017 at 12:49 PM, Martin Liška <mli...@suse.cz> wrote:
>>>
>>> On 06/09/2017 12:39 PM, Richard Biener wrote:
>>>>
>>>>
>>>> On Fri, Jun 9, 2017 at 12:17 PM, Martin Liška <mli...@suse.cz> wrote:
>>>>>
>>>>>
>>>>> On 06/09/2017 12:12 PM, Richard Biener wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Fri, Jun 9, 2017 at 11:29 AM, Martin Liška <mli...@suse.cz> wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On 06/08/2017 03:47 PM, Jakub Jelinek wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> Hi!
>>>>>>>>
>>>>>>>> I'd still prefer to handle it with the flags infrastructure instead,
>>>>>>>> but
>>>>>>>> if
>>>>>>>> Richard wants to do it this way, then at least:
>>>>>>>>
>>>>>>>> On Thu, Jun 08, 2017 at 03:30:49PM +0200, Martin Liška wrote:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> +/* Return true when flag_sanitize & FLAG is non-zero.  If FN is
>>>>>>>>> non-null,
>>>>>>>>> +   remove all flags mentioned in "no_sanitize_flags" of
>>>>>>>>> DECL_ATTRIBUTES.
>>>>>>>>> */
>>>>>>>>> +
>>>>>>>>> +bool
>>>>>>>>> +sanitize_flags_p (unsigned int flag, const_tree fn)
>>>>>>>>> +{
>>>>>>>>> +  unsigned int result_flags = flag_sanitize & flag;
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> This function really should be either inline, or partly inline,
>>>>>>>> partly
>>>>>>>> out
>>>>>>>> of line, to handle the common case (sanitization of something not
>>>>>>>> enabled)
>>>>>>>> in the fast path.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Hello.
>>>>>>>
>>>>>>> Having that inlined would be great, however we'll need to put it to
>>>>>>> tree.h
>>>>>>> and thus we have to include "options.h" before tree.h in multiple
>>>>>>> source
>>>>>>> files.
>>>>>>> Please take a look at partial patch.
>>>>>>>
>>>>>>>>
>>>>>>>> And, it should have an early out,
>>>>>>>>       if (result_flags == 0)
>>>>>>>>         return false;
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Good idea!
>>>>>>>
>>>>>>>>
>>>>>>>>> +
>>>>>>>>> +  if (fn != NULL_TREE)
>>>>>>>>> +    {
>>>>>>>>> +      tree value = lookup_attribute ("no_sanitize_flags",
>>>>>>>>> DECL_ATTRIBUTES (fn));
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> The attribute, if it is internal only, should have spaces or similar
>>>>>>>> characters in its name, like "fn spec", "omp declare target" and
>>>>>>>> many
>>>>>>>> others.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Done that.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> Whoo, wait -- this is for internal use only?  Can you step back and
>>>>>> explain
>>>>>> why we need this?  We do, after all, have -fsanitize options already.
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> Can be seen here:
>>>>>
>>>>> __attribute__((no_sanitize_thread, no_sanitize ("null"), no_sanitize
>>>>> ("address"), no_sanitize ("undefined"), no_sanitize ("address"),
>>>>> sanitize
>>>>> no_flags (16777195)))
>>>>> fn1 ()
>>>>> {
>>>>> ...
>>>>> }
>>>>>
>>>>> where no_sanitize_thread and no_sanitize are normal attributes used by
>>>>> users.
>>>>> But we want to aggregate all there attributes and build one integer
>>>>> mask
>>>>> that
>>>>> will drive sanitize_flags_p. And that's why we introduced 'sanitize
>>>>> no_flags'
>>>>> attribute, so that we don't have to iterate all attrs every time in
>>>>> anitize_flags_p.
>>>>>
>>>>> Hope it explains situation?
>>>>
>>>>
>>>>
>>>> Hum, ok ... but then you can "simply" have the no_sanitize attribute
>>>> internal rep use a INTEGER_CST instread of a STRING_CST value,
>>>> updating that in handle_attribute instead of adding new attributes?
>>>>
>>>> There's nothing that forces internal representation to match what the
>>>> user wrote.
>>>
>>>
>>>
>>> I see, but consider following test-case:
>>>
>>> void
>>> __attribute__((no_sanitize_thread))
>>> __attribute__((no_sanitize(("address"))))
>>> __attribute__((no_sanitize(("undefined"))))
>>> __attribute__((no_sanitize(("address"))))
>>> __attribute__((no_sanitize(("null"))))
>>> foo (void) {}
>>>
>>> handle_no_sanitize_thread_attribute function is called for
>>> no_sanitize_thread and
>>> changing first no_sanitize attribute to integer is wrongly doable.
>>
>>
>> Just change no_sanitize_thread to add no_sanitize instead?
>
>
> Unfortunately, we currently support no_sanitize_{address,thread,undefined}
> and no_address_safety_analysis. Thus we can't drop these.

Sure, but the internal representation of no_sanitize_{address,thread,undefined}
can be the same as no_sanitize("...").  Just add *no_add_attrs = true and
append/change no_sanitize in the handler.

>
>>
>>> Apart
>>> from that,
>>> we want to merge all flags to a single attribute. Thus said, having an
>>> unique name
>>> will enable this.
>>
>>
>> no_sanitize looks like the unique name to me -- I suppose
>> no_sanitize("thread")
>> works?
>
>
> Yep, it's unique but as I mentioned we've got const struct attribute_spec
> c_common_attribute_table[]
> handlers that are executed on these no sanitize attributes. And as I want to
> store int mask to
> an attribute, I prefer to come up with a new attribute "sanitize no_flags"
> and I can set
>   *no_add_attrs = true; in order to remove the original attributes:
>
> void
> __attribute__((no_sanitize(("address"))))
> __attribute__((no_sanitize(("undefined"))))
> __attribute__((no_sanitize(("address"))))
> __attribute__((no_sanitize(("null"))))
> fn1 (void) { char *ptr; char *ptr2; { char my_char[9]; ptr = &my_char[0];
> __builtin_memcpy (&ptr2, &ptr, sizeof (ptr2)); } *(ptr2+9) = 'c'; }
>
> will become:
>
> __attribute__((sanitize no_flags (16777187)))
> fn1 ()
> {
> ...
> }
>
> I'm going to test that.
>
> Martin
>
>
>>
>> Richard.
>>
>>> Martin
>>>
>>>
>>>>
>>>> [historically we've used random flags in decls/types for this kind of
>>>> caching
>>>> but I can see we don't want to waste as many bits there]
>>>>
>>>> Richard.
>>>>
>>>>> Martin
>>>>>
>>>>>
>>>>>>
>>>>>> Richard.
>>>>>>
>>>>>>>>
>>>>>>>> +add_no_sanitize_value (tree node, unsigned int flags)
>>>>>>>> +{
>>>>>>>> +  tree attr = lookup_attribute ("no_sanitize_flags",
>>>>>>>> DECL_ATTRIBUTES
>>>>>>>> (node));
>>>>>>>> +  if (attr)
>>>>>>>> +    {
>>>>>>>> +      unsigned int old_value = tree_to_uhwi (TREE_VALUE (attr));
>>>>>>>> +      flags |= old_value;
>>>>>>>> +    }
>>>>>>>> +
>>>>>>>> +  DECL_ATTRIBUTES (node)
>>>>>>>> +    = tree_cons (get_identifier ("no_sanitize_flags"),
>>>>>>>> +                build_int_cst (unsigned_type_node, flags),
>>>>>>>> +                DECL_ATTRIBUTES (node));
>>>>>>>>
>>>>>>>> If there is a previous attribute already, can't you modify it in
>>>>>>>> place?  If not, as it could be perhaps shared? with other functions
>>>>>>>> somehow, at least you should avoid adding a new attribute if
>>>>>>>> (old_value | flags) == old_value.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Yep, we should definitely share, I'll add test-case for that.
>>>>>>> I'm currently testing the incremental patch, may I install it
>>>>>>> after regression tests?
>>>>>>>
>>>>>>> Martin
>>>>>>>
>>>>>>>>
>>>>>>>>            Jakub
>>>>>>>>
>>>>>>>
>>>>>
>>>
>

Reply via email to