On Wed, Jan 24, 2024 at 12:29:51AM +0000, Qing Zhao wrote: > This is the 4th version of the patch.
Thanks very much for this! I tripped over an unexpected behavioral change that the Linux kernel depends on: __builtin_types_compatible_p() no longer treats an array marked with counted_by as different from that array's decayed pointer. Specifically, the kernel uses these macros: /* * Force a compilation error if condition is true, but also produce a * result (of value 0 and type int), so the expression can be used * e.g. in a structure initializer (or where-ever else comma expressions * aren't permitted). */ #define BUILD_BUG_ON_ZERO(e) ((int)(sizeof(struct { int:(-!!(e)); }))) #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) /* &a[0] degrades to a pointer: a different type from an array */ #define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) This gets used in various places to make sure we're dealing with an array for a macro: #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) So this builds: struct untracked { int size; int array[]; } *a; __must_be_array(a->array) => 0 (as expected) __builtin_types_compatible_p(typeof(a->array), typeof(&(a->array)[0])) => 0 (as expected, array vs decayed array pointer) But if counted_by is added, we get a build failure: struct tracked { int size; int array[] __counted_by(size); } *b; __must_be_array(b->array) => build failure (not expected) __builtin_types_compatible_p(typeof(b->array), typeof(&(b->array)[0])) => 1 (not expected, both pointers?) -- Kees Cook