Re: Handling C2Y zero-length operations on null pointers

2024-10-07 Thread Jakub Jelinek via Gcc
On Fri, Oct 04, 2024 at 12:42:24AM +0200, Florian Weimer wrote:
> * Joseph Myers:
> 
> > The real question is how to achieve optimal warnings in the absence of the 
> > attribute.  Should we have a variant of the nonnull attribute that warns 
> > for NULL arguments but without optimizing based on them?
> 
> I think attribute access already covers part of it:
> 
> #include 
> void read_array (void *, size_t) __attribute__ ((access (read_only, 1, 2)));
> void
> f (void)
> {
>   read_array (NULL, 0); // No warning.
>   read_array (NULL, 1); // Warning.
> }
> 
> It does not work for functions like strndup that support both string
> arguments (of any length) and array arguments of a specified size.
> The read_only variant requires an initialized array of the specified
> length.

access attribute can't deal with various other things.

Consider the qsort case.  My understanding was that the paper is making
typedef int (*cmpfn) (const void *, const void *);
qsort (NULL, 0, 1, (cmpfn) NULL);
valid (but is
qsort (NULL, 1, 0, (cmpfn) NULL);
still invalid?).
How do you express that with access attribute, which can only have 1 size
argument?  The accessed memory for the read/write pointee of the first
argument has nmemb * size parameter bytes size.
And using access attribute for function pointers doesn't work, there is
no data to be read/written there, just code.

Guess some of the nonnull cases could be replaced by access attribute
if we clarify the documentation that if SIZE_INDEX is specified and that
argument is non-zero then the pointer has to be non-NULL, and teach
sanitizers etc. to sanitize those.

For the rest, perhaps we need some nonnull_if_nonzero argument
which requires that the parameter identified by the first attribute
argument must be pointer which is non-NULL if the parameter identified
by the second attribute argument is non-zero.
And get clarified the qsort/bsearch cases whether it is about just
nmemb == 0 or nmemb * size == 0.

Jakub



Re: Handling C2Y zero-length operations on null pointers

2024-10-07 Thread Florian Weimer
* Jakub Jelinek:

> How do you express that with access attribute, which can only have 1
> size argument?

Don't we sometimes use inline functions to handle such special cases?

> For the rest, perhaps we need some nonnull_if_nonzero argument
> which requires that the parameter identified by the first attribute
> argument must be pointer which is non-NULL if the parameter identified
> by the second attribute argument is non-zero.
> And get clarified the qsort/bsearch cases whether it is about just
> nmemb == 0 or nmemb * size == 0.

C does not support zero-sized objects, so that's something for us to
figure out on our own.  We can treat size == 0 as invalid because the
functions can't work, as they use pointers for the comparison function
and not array indices.


Re: Assembly-level peepholes?

2024-10-07 Thread Richard Biener via Gcc
On Fri, Oct 4, 2024 at 1:47 PM Sid Maxwell via Gcc  wrote:
>
> I haven't found anything in my digging, so I'd like to ask if anyone knows
> of any mechanism in GCC for conducting peephole optimization on generated
> code.  I can imagine doing this as a pass over the generated code from
> within the backend, or as a separate process between cc1 and as.  I'm
> working with a derivative of 4.3.

There's define_peephole and define_peephole2 in the machine description.
It works on RTL of course but is essentially what you are looking for?

Richard.

>
> -+- Sid


Re: Handling C2Y zero-length operations on null pointers

2024-10-07 Thread Qing Zhao via Gcc


> On Oct 7, 2024, at 11:22, Jakub Jelinek  wrote:
> 
> On Mon, Oct 07, 2024 at 03:14:22PM +, Qing Zhao wrote:
>>> Consider the qsort case.  My understanding was that the paper is making
>>> typedef int (*cmpfn) (const void *, const void *);
>>> qsort (NULL, 0, 1, (cmpfn) NULL);
>>> valid (but is
>>> qsort (NULL, 1, 0, (cmpfn) NULL);
>>> still invalid?).
>>> How do you express that with access attribute, which can only have 1 size
>>> argument?  The accessed memory for the read/write pointee of the first
>>> argument has nmemb * size parameter bytes size.
>> 
>> For the other attribute “alloc_size”, we have two forms, 
>> A. alloc_size (position)
>> and
>> B. alloc_size (position-1, position-2)
>> 
>> The 2nd form is used to represent nmemb * size. 
>> 
>> Is it possible that we extend the attribute “access” similarly? 
>> 
>> Then we can use the attribute “access” consistently for this purpose?
> 
> We could do that and express the array pointer of qsort/bsearch that way.
> But there is also the function pointer case, there we don't access any bytes
> (and what exactly a function pointer means depends on architecture, can be
> code pointer, or can be pointer to function descriptor etc.), so we really
> need to express this pointer must be non-NULL if some other argument (or
> their product?) is non-0.

I have a question here (maybe a stupid question-:): do we really need to 
express such situation for function pointers? 
I cannot construct a use case for this…

Qing

> If one passes constant(s) to those arguments, then such checking can be
> done through a warning like we warn for passing NULL to nonnull attributed
> parameters right now (or not if 0), if it is non-constant, then it can be
> diagnosed in sanitizers.
> 
> Jakub
> 



Re: Handling C2Y zero-length operations on null pointers

2024-10-07 Thread Qing Zhao via Gcc


> On Oct 7, 2024, at 10:13, Jakub Jelinek via Gcc  wrote:
> 
> On Fri, Oct 04, 2024 at 12:42:24AM +0200, Florian Weimer wrote:
>> * Joseph Myers:
>> 
>>> The real question is how to achieve optimal warnings in the absence of the 
>>> attribute.  Should we have a variant of the nonnull attribute that warns 
>>> for NULL arguments but without optimizing based on them?
>> 
>> I think attribute access already covers part of it:
>> 
>> #include 
>> void read_array (void *, size_t) __attribute__ ((access (read_only, 1, 2)));
>> void
>> f (void)
>> {
>>  read_array (NULL, 0); // No warning.
>>  read_array (NULL, 1); // Warning.
>> }
>> 
>> It does not work for functions like strndup that support both string
>> arguments (of any length) and array arguments of a specified size.
>> The read_only variant requires an initialized array of the specified
>> length.
> 
> access attribute can't deal with various other things.
> 
> Consider the qsort case.  My understanding was that the paper is making
> typedef int (*cmpfn) (const void *, const void *);
> qsort (NULL, 0, 1, (cmpfn) NULL);
> valid (but is
> qsort (NULL, 1, 0, (cmpfn) NULL);
> still invalid?).
> How do you express that with access attribute, which can only have 1 size
> argument?  The accessed memory for the read/write pointee of the first
> argument has nmemb * size parameter bytes size.

For the other attribute “alloc_size”, we have two forms, 
A. alloc_size (position)
and
B. alloc_size (position-1, position-2)

The 2nd form is used to represent nmemb * size. 

Is it possible that we extend the attribute “access” similarly? 

Then we can use the attribute “access” consistently for this purpose?

Qing

> And using access attribute for function pointers doesn't work, there is
> no data to be read/written there, just code.
> 
> Guess some of the nonnull cases could be replaced by access attribute
> if we clarify the documentation that if SIZE_INDEX is specified and that
> argument is non-zero then the pointer has to be non-NULL, and teach
> sanitizers etc. to sanitize those.
> 
> For the rest, perhaps we need some nonnull_if_nonzero argument
> which requires that the parameter identified by the first attribute
> argument must be pointer which is non-NULL if the parameter identified
> by the second attribute argument is non-zero.
> And get clarified the qsort/bsearch cases whether it is about just
> nmemb == 0 or nmemb * size == 0.
> 
> Jakub
> 



Re: Handling C2Y zero-length operations on null pointers

2024-10-07 Thread Jakub Jelinek via Gcc
On Mon, Oct 07, 2024 at 03:14:22PM +, Qing Zhao wrote:
> > Consider the qsort case.  My understanding was that the paper is making
> > typedef int (*cmpfn) (const void *, const void *);
> > qsort (NULL, 0, 1, (cmpfn) NULL);
> > valid (but is
> > qsort (NULL, 1, 0, (cmpfn) NULL);
> > still invalid?).
> > How do you express that with access attribute, which can only have 1 size
> > argument?  The accessed memory for the read/write pointee of the first
> > argument has nmemb * size parameter bytes size.
> 
> For the other attribute “alloc_size”, we have two forms, 
> A. alloc_size (position)
> and
> B. alloc_size (position-1, position-2)
> 
> The 2nd form is used to represent nmemb * size. 
> 
> Is it possible that we extend the attribute “access” similarly? 
> 
> Then we can use the attribute “access” consistently for this purpose?

We could do that and express the array pointer of qsort/bsearch that way.
But there is also the function pointer case, there we don't access any bytes
(and what exactly a function pointer means depends on architecture, can be
code pointer, or can be pointer to function descriptor etc.), so we really
need to express this pointer must be non-NULL if some other argument (or
their product?) is non-0.
If one passes constant(s) to those arguments, then such checking can be
done through a warning like we warn for passing NULL to nonnull attributed
parameters right now (or not if 0), if it is non-constant, then it can be
diagnosed in sanitizers.

Jakub