https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128094

--- Comment #3 from lightofmysoul at gmail dot com ---
Created attachment 65932
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65932&action=edit
container_of: pointer arithmetic vs uintptr_t

Thanks for the explanation! I understand the strict reading, but GCC seems
to support this idiom on purpose: PR 120780 added it, and its test
(builtin-dynamic-object-size-pr120780.c, test3) does the same through a
char * and expects the correct sizes. The only difference in my case is
that the member is an int, not a char array.

GCC also returns 8 for __builtin_object_size(buf, 1), 12 for
__builtin_dynamic_object_size(buf, 0), and 8 when x is an int *. Only
__builtin_dynamic_object_size(buf, 1) through a char * or void * gives 0.

I moved my container_of from uintptr_t to pointer arithmetic because
with uintptr_t the compilers lose track of the object.

The attached uintptr.c shows it for GCC (gcc -O2 -S uintptr.c, with and without
-DUINTPTR): with uintptr_t the out-of-bounds write in oob() is no longer
warned about, and two() has to reload sa->buf[0].

And additionally with clang it is even worse: its fortify and UBSan miss real
overflows, and more asm is generated...

Reply via email to