> On Aug 26, 2024, at 16:30, Kees Cook <k...@kernel.org> wrote:
> 
> On Mon, Aug 26, 2024 at 07:30:15PM +0000, Qing Zhao wrote:
>> Hi, Martin,
>> 
>> Looks like that there is some issue when I tried to use the _Generic for the 
>> testing cases, and then I narrowed down to a
>> small testing case that shows the problem without any change to GCC.
>> 
>> [opc@qinzhao-ol8u3-x86 gcc]$ cat t1.c
>> struct annotated {
>>  char b;
>>  int c[];
>> } *array_annotated;  
>> extern void * counted_by_ref (int *);
>> 
>> int main(int argc, char *argv[])
>> {
>>  typeof(counted_by_ref (array_annotated->c)) ret
>>    = counted_by_ref (array_annotated->c); 
>>   _Generic (ret, void* : (void)0, default: *ret = 10);
>> 
>>  return 0;
>> }
>> [opc@qinzhao-ol8u3-x86 gcc]$ /home/opc/Install/latest/bin/gcc t1.c
>> t1.c: In function ‘main’:
>> t1.c:12:44: warning: dereferencing ‘void *’ pointer
>>   12 |   _Generic (ret, void* : (void)0, default: *ret = 10);
>>      |                                            ^~~~
>> t1.c:12:49: error: invalid use of void expression
>>   12 |   _Generic (ret, void* : (void)0, default: *ret = 10);
>>      |                                                 ^
> 
> I implemented it like this[1] in the Linux kernel. So yours could be:
> 
> struct annotated {
>  char b;
>  int c[] __attribute__((counted_by(b));
> };
> extern struct annotated *array_annotated;
> 
> int main(int argc, char *argv[])
> {
>  typeof(_Generic(__builtin_get_counted_by(array_annotated->c),
>    void *: (size_t *)NULL,
>    default: __builtin_get_counted_by(array_annotated->c)))
> ret = __builtin_get_counted_by(array_annotated->c);
>  if (ret)
> *ret = 10;
> 
>  return 0;
> }
> 
> It's a bit cumbersome, but it does what's needed.
> 
> This is, however, just doing exactly what Bill has suggested: it is
> converting the (void *)NULL into (size_t *)NULL when there is no
> counted_by annotation...

That’s the reason why I returned a (size_t *) instead of a (void *) for the 
NULL pointer when there is no counted_by annotation in the 1st version of the 
patch, then the conversion from (void *) NULL to (size_t *) NULL in the source 
code level will not be needed.

Then the above can be simplified as:

typeof (__builtin_get_counted_by(array_annotated->c)) ret = 
__builtin_get_counted_by(array_annotated->c);

If (ret) *ret = 10;

I am wondering shall I still keep the (size_t *) for the returned NULL pointer 
instead of the (void *)?

Qing


> 
> -Kees
> 
> [1] 
> https://lore.kernel.org/linux-hardening/20240822231324.make.666-k...@kernel.org/
> 
> -- 
> Kees Cook


Reply via email to