On Mon, Jan 29, 2024 at 10:45:23PM +0000, Qing Zhao wrote: > There are two things here. > > 1. The value of the “counted-by” is 0; (which is easy to be understood) > 2. The result of the _builtin_object_size when see a “counted-by” 0. > > For 1, it’s simple, if we see a counted-by value <= 0, then counted-by is 0;
Okay, that's good; this matches my understanding. :) > But for 2, when the _builtin_object_size sees a “counted-by” 0, what’s value > it will return for the object size? > > Can we return 0 for the object size? I don't see why not. For example: // -O2 -fstrict-flex-arrays=3 struct s { int a; int b[4]; } foo; #define report(x) printf("%s: %zu\n", #x, (size_t)(x)) int main(int argc, char *argv[]) { struct s foo; report(__builtin_dynamic_object_size(&foo.b[4], 0)); report(__builtin_dynamic_object_size(&foo.b[5], 0)); report(__builtin_dynamic_object_size(&foo.b[-10], 0)); report(__builtin_dynamic_object_size(&foo.b[4], 1)); report(__builtin_dynamic_object_size(&foo.b[5], 1)); report(__builtin_dynamic_object_size(&foo.b[-10], 1)); report(__builtin_dynamic_object_size(&foo.b[4], 2)); report(__builtin_dynamic_object_size(&foo.b[5], 2)); report(__builtin_dynamic_object_size(&foo.b[-10], 2)); report(__builtin_dynamic_object_size(&foo.b[4], 3)); report(__builtin_dynamic_object_size(&foo.b[5], 3)); report(__builtin_dynamic_object_size(&foo.b[-10], 3)); return 0; } shows: __builtin_dynamic_object_size(&foo.b[4], 0): 0 __builtin_dynamic_object_size(&foo.b[5], 0): 0 __builtin_dynamic_object_size(&foo.b[-10], 0): 0 __builtin_dynamic_object_size(&foo.b[4], 1): 0 __builtin_dynamic_object_size(&foo.b[5], 1): 0 __builtin_dynamic_object_size(&foo.b[-10], 1): 0 __builtin_dynamic_object_size(&foo.b[4], 2): 0 __builtin_dynamic_object_size(&foo.b[5], 2): 0 __builtin_dynamic_object_size(&foo.b[-10], 2): 0 __builtin_dynamic_object_size(&foo.b[4], 3): 0 __builtin_dynamic_object_size(&foo.b[5], 3): 0 __builtin_dynamic_object_size(&foo.b[-10], 3): 0 This is showing "no bytes left" for the end of the b array, and if this index keeps going, it still reports 0 if we're past the end of the object completely. And it is similarly capped for negative indexes. This is true for all the __bos type bits. A "counted-by" of 0 (or below) would have the same meaning as an out of bounds index here. > (As I mentioned in the previous email, 0 in __builtin_object_size doesn’t > mean size 0, > it means UNKNOWN_SIZE when the type is 2/3, So, what’s value we should > return for the size 0?) > https://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html I think I see what you mean, but I still think it should be 0 for 2/3, regardless of the documented interpretation. If that's the current response for a pathological index under 2/3, then I think it's totally reasonable that it should do the same for pathological bounds. And BTW, it seems there are 0-sized objects, though maybe they're some kind of special case: struct s { int a; struct { } nothing; int b; }; #define report(x) printf("%s: %zu\n", #x, (size_t)(x)) int main(int argc, char *argv[]) { struct s foo; report(__builtin_dynamic_object_size(&foo.nothing, 1)); } shows: __builtin_dynamic_object_size(&foo.nothing, 1): 0 -Kees -- Kees Cook