Handling C2Y zero-length operations on null pointers
Qing Zhao
qing.zhao@oracle.com
Wed Nov 13 19:47:11 GMT 2024
> On Nov 12, 2024, at 01:51, Martin Uecker <uecker@tugraz.at> wrote:
>
> Am Montag, dem 07.10.2024 um 15:14 +0000 schrieb Qing Zhao:
>>
>>> On Oct 7, 2024, at 10:13, Jakub Jelinek via Gcc <gcc@gcc.gnu.org> 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 <stddef.h>
>>>> 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?
>
> We also miss sanitizer support.
>
> How about letting "access" only be about access range
> and instead have separate attribute that can be used to
> express more complicated preconditions?
Sounds reasonable to me.
Yes, it’s not a good idea to mix them together with one attribute.
Qing
>
> void* foo(void *p, size_t mmemb, size_t size)
> [[precondition((p == NULL) == (mmemb * size == 0)]];
>
> (not saying this is the right condition for any function
> in the standard library)
>
> Martin
>
>>
>> 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
More information about the Gcc
mailing list