Re: Handling C2Y zero-length operations on null pointers
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
* 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?
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
> 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
> 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
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