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