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...

-Kees

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

-- 
Kees Cook

Reply via email to